Regular expression dictionary in python

15,177

Solution 1

Yes, it's perfectly possible:

import re
dict = {}
dict[re.compile('actionname (\d+) (\d+)')] = method
dict[re.compile('differentaction (\w+) (\w+)')] = appropriate_method

def execute_method_for(str):
    #Match each regex on the string
    matches = (
        (regex.match(str), f) for regex, f in dict.iteritems()
    )

    #Filter out empty matches, and extract groups
    matches = (
        (match.groups(), f) for match, f in matches if match is not None
    )


    #Apply all the functions
    for args, f in matches:
        f(*args)

Solution 2

Of course, the values of your dictionary can be python functions.

Your matching function can try to match your string to each key and execute appropriate function if there is a match. This will be linear in time in the best case, but I don't think you can get anything better if you want to use regular expressions.

But looking at your example data I think you should reconsider whether you need regular expressions at all. Perhaps you can just parse your input string into, e.g. <procedure-name> <parameter>+ and then lookup appropriate procedure by it's name (simple string), that can be O(1)

Solution 3

Unfortunately this is not possible. You will need to iterate over the regular expressions in order to find out if they match. The lookup in the dictionary will be O(1) though (but that doesn't solve your problem).

Solution 4

IMHO, you are asking the WRONG QUESTION.

  1. You ask if there's an elegant way to do this. Answer: The most elegant way is the most OBVIOUS way. Code will be read 10x to 20x as often as it's modified. Therefore, if you write something 'elegant' that's hard to read and quickly understand, you've just sabotaged the guy after you who has to modify it somehow.

  2. BETTER CODE:

Another answer here reads like this:

matches = ( (regex.match(str), f) for regex, f in dict.iteritems() )

This is functionally equivalent (IMPORTANTLY, the same in terms of Python generated bytecode) to:

# IMHO 'regex' var should probably be named 'pattern' since it's type is <sre.SRE_Pattern>

for pattern, func in dictname.items():
    if pattern.match(str):
        func()

But, the below sample is hugely easier to read and understand at a glance.

I apologize (a little) if you're one of those people who is offended by code that is even slightly more wordy than you think it could be. My criteria, and Guido's as mentioned in PEP-8, is that the clearest code is the best code.

Share:
15,177
18bytes
Author by

18bytes

A hacker.

Updated on June 04, 2022

Comments

  • 18bytes
    18bytes almost 2 years

    Is it possible to implement a dictionary with keys as regular expressions and actions (with parameters) as values?

    for e.g.

    1. key = "actionname 1 2", value = "method(1, 2)"
    2. key = "differentaction par1 par2", value = "appropriate_method(par1, par2)"

    User types in the key, i need to execute the matching method with the parameters provided as part of user input.

    It would be great if we can achieve the lookup in O(1) time, even if its not possible atleast i am looking for solutions to solve this problem.

    I will be having few hundred regular expressions (say 300) and matching parameterized actions to execute.

    I can write a loop to achieve this, but is there any elegant way to do this without using a for loop?

    Related question: Hashtable/dictionary/map lookup with regular expressions

  • 18bytes
    18bytes almost 12 years
    When there is a match i want to invoke the method with the parameters provided, i am looking for an elegant way to do this.
  • 18bytes
    18bytes almost 12 years
    Is it possible to use named groups in regex and map it with equivalent named method arguments?
  • Eric
    Eric almost 12 years
    In principle, yes. I don't recall how you iterate over named groups.
  • Eric
    Eric almost 12 years
    @devsunder: Ok got it: use groupdict() in place of groups(), and **args in place of *args
  • HardlyKnowEm
    HardlyKnowEm over 11 years
    What exactly is the advantage of a dict here? The O(1) access of a dict does not have any advantages if you have to iterate through it every time. You could use a list of tuples, (list = [(re.compile('actionname (\d+)'), method), ...]) and then use for regex, f in list. This would use less memory than a dict.
  • Eric
    Eric over 11 years
    @mlefavor: I'd say that a dictionary is more semantically valid, since a one to many replace would make no sense. However, I agree a list of tipped would be more efficient.