【问题标题】:Regular expression dictionary in pythonpython中的正则表达式字典
【发布时间】:2012-06-11 11:05:32
【问题描述】:

是否可以实现一个字典,其中键作为正则表达式,动作(带参数)作为值?

例如

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

用户键入键,我需要使用作为用户输入的一部分提供的参数执行匹配方法。

如果我们能在O(1) 时间内完成查找,那就太好了,即使这不可能,至少我正在寻找解决这个问题的解决方案。

我将有几百个正则表达式(比如300)和匹配的参数化操作来执行。

我可以编写一个循环来实现这一点,但是有没有什么优雅的方法可以在不使用 for 循环的情况下做到这一点?

相关问题:Hashtable/dictionary/map lookup with regular expressions

【问题讨论】:

  • 如果输入匹配多个正则表达式怎么办?
  • 我只需要第一场比赛。可以有匹配列表,但不是必需的。
  • 很好地了解我的答案

标签: python regex performance mapping


【解决方案1】:

是的,完全有可能:

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)

【讨论】:

  • 是否可以在正则表达式中使用命名组并将其映射到等效的命名方法参数?
  • 原则上是的。我不记得你是如何遍历命名组的。
  • @devsunder:好的:用groupdict()代替groups(),用**args代替*args
  • dict 的优势到底是什么?如果您每次都必须遍历它,那么对 dict 的 O(1) 访问没有任何优势。您可以使用元组列表 (list = [(re.compile('actionname (\d+)'), method), ...]),然后使用 for regex, f in list。这将比dict 使用更少的内存。
  • @mlefavor:我想说字典在语义上更有效,因为一对多替换没有意义。但是,我同意小费列表会更有效。
【解决方案2】:

当然,你的字典的值可以是python函数。

您的匹配函数可以尝试将您的字符串与每个键匹配,并在匹配时执行相应的函数。在最好的情况下,这将是线性的,但我认为如果你想使用正则表达式,你可以得到更好的结果。

但是查看您的示例数据,我认为您应该重新考虑是否需要正则表达式。也许您可以将输入字符串解析为例如<procedure-name> <parameter>+ 然后通过其名称(简单字符串)查找适当的过程,可以是 O(1)

【讨论】:

  • 当有匹配时我想用提供的参数调用方法,我正在寻找一种优雅的方式来做到这一点。
【解决方案3】:

很遗憾,这是不可能的。您将需要遍历正则表达式以找出它们是否匹配。字典中的查找将是 O(1)(但这并不能解决您的问题)。

【讨论】:

    【解决方案4】:

    恕我直言,您问的是错误的问题

    1. 你问是否有一种优雅的方式来做到这一点。回答:最优雅的方式是最明显的方式。 代码被修改的频率会增加 10 到 20 倍。因此,如果你写了一些难以阅读和快速理解的“优雅”的东西,那么你只是在破坏必须以某种方式修改它的人。

    2. 更好的代码:

    这里的另一个答案是这样的:

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

    这在功能上等同(重要的是,在 Python 生成的字节码方面相同):

    # 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()
    

    但是,下面的示例一目了然更容易阅读和理解

    如果您是那些被比您想象的更冗长的代码冒犯的人之一,我向您道歉(有点)。我的标准和 PEP-8 中提到的 Guido 的标准是,最清晰的代码就是最好的代码。

    【讨论】:

      猜你喜欢
      • 2013-08-13
      • 1970-01-01
      • 2015-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      • 2022-01-22
      相关资源
      最近更新 更多