7

这对于一些问题非常方便:

>>> re.search('(?P<b>.b.).*(?P<i>.i.)', 'abcdefghijk').groupdict()
{'i': 'hij', 'b': 'abc'}

但是,如果我不知道提前预期的顺序怎么办?

[更新]

例如,假设我有一个包含一些未知字符顺序的输入变量,而 'b' 恰好出现在 'i' 之后。我希望仍然能够为 '.b.' 引用组。和我。' 无需根据输入变量中的顺序订购我的正则表达式。所以,我希望我能做这样的事情,但我不知道这是否可能:

>>> re.search('(?P<b>.b.)|(?P<i>.i.)', unknown_order_alphabet_str).groupdict()
{'i': 'hij', 'b': 'abc'}

[结束更新]

我四处搜索并绞尽脑汁,但无法产生任何好的线索。猜测此功能不存在,因为 re 执行此操作的唯一方法可能是为每个组扫描整个字符串一次(当然我可以在循环中执行此操作)但我想我会看到 stackoverflow 的大脑不得不说。

谢谢你的帮助,
乔希

4

5 回答 5

1

在 RE 模式中使用竖线(“或”),并finditer获取所有感兴趣的匹配对象:每个对象都有一个groupdictwithNone作为未参与该匹配的组的值,您可以根据需要“合并”字典.

例如:

import re

def mergedgroupdict(pattern, thestring):
  there = re.compile(pattern)
  result = {}
  for mo in there.finditer(thestring):
    d = mo.groupdict()
    for k in d:
      if k not in result and d[k] is not None:
        result[k] = d[k]
  return result

这使用了一种合并策略,该策略只是为模式中的每个命名组选择第一个实际匹配项。现在例如

>>> mergedgroupdict('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk')
{'i': 'hij', 'b': 'abc'}
>>> mergedgroupdict('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk'[::-1])
{'i': 'jih', 'b': 'cba'}

如果我正确解释您的问题,大概如您所愿。

于 2010-02-02T22:07:38.103 回答
0
>>> [m.groupdict() for m in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk')]
[{'i': None, 'b': 'abc'}, {'i': 'hij', 'b': None}]

似乎工作正常,但如果你有很多组检查哪个不是None可能会变得乏味。

这将查找字符串中的.b.所有.i.匹配项。如果您想确保它找到了每一个,您也必须手动检查它。

于 2010-02-02T22:06:58.503 回答
0

我能得到的最接近的是:

>>> [match.groupdict() for match in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk')]
[{'i': None, 'b': 'abc'}, {'i': 'hij', 'b': None}]

然后,如何组合字典取决于您是否期望多个匹配项。如果你只想要一场比赛,你可以这样做:

>>> results = {}
>>> for match in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk'):
...     results.update(dict((k,v) for k, v in match.groupdict().iteritems() if v is not None))
... 
>>> results
{'i': 'hij', 'b': 'abc'}

或者对于多个匹配:

>>> results = defaultdict(lambda: [])
>>> for match in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijkabcdefghijk'):
...     for k, v in match.groupdict().iteritems():
...         if v is not None:
...             results[k].append(v)
... 
>>> results
defaultdict(<function <lambda> at 0x7f53d0992c08>, {'i': ['hij', 'hij'], 'b': ['abc', 'abc']})
于 2010-02-02T22:08:40.003 回答
0

这是一种不需要finditer字典合并的方法:

>>> pat = re.compile(r'(?:.*?(?:(?P<b>.b.)|(?P<i>.i.))){2}')

>>> pat.search('abcdefghijk').groupdict()
{'i': 'hij', 'b': 'abc'}

>>> pat.search('aicdefghbjk').groupdict()
{'i': 'aic', 'b': 'hbj'}

这是假设每个字符在您的 stringb中只i出现一次,否则:

  • 如果其中一个字符可能丢失,您可以使用{,2}代替{2}.
  • 如果其中一个字符出现不止一次,则搜索将检索其中任何一个的前两次出现(例如,它可以找到b两次但根本找不到i)。
于 2013-02-27T13:11:53.753 回答
0

这是一次轻扫游戏的迟到者,初学者也可以阅读:

>>> dict([(name, re.search(pattern, "abcdefghijk").group())
          for name, pattern in {"b": ".b.", "i": ".i"}.items()])  
{'b': 'abc', 'i': 'hij'}
于 2017-08-05T10:19:55.917 回答