【问题标题】:Grouping elements based on an identifier in regular expression基于正则表达式中的标识符对元素进行分组
【发布时间】:2013-08-08 16:45:34
【问题描述】:

我有一个长字符串,看起来像:

s = 'label("id1","A") label("id1","B") label("id2", "C") label("id2","A") label("id2","D") label("id3","A")'

我想使用正则表达式根据 id 创建标签列表。

为了更清楚,从示例中的字符串s 中,我想得到一个结果列表,如下所示:

[("id1", ["A","B"]),
 ("id2", ["C","A","D"]),
 ("id3", ["A"])]

使用正则表达式我设法获取了 id 和元素:

import re
regex = re.compile(r'label\((\S*),(\S*)\)')
results = re.findall(regex,s)

使用此代码,results 看起来像:

[('"id1"', '"A"'),
 ('"id1"', '"B"'),
 ('"id2"', '"A"'),
 ('"id2"', '"D"'),
 ('"id3"', '"A"')]

有没有一种简单的方法可以从正则表达式中获取已经正确分组的数据?

【问题讨论】:

  • 在想要的结果中,我将元素分组到一个列表中(例如 ["A","B"],但即使是元组或集合也可以!
  • id 总是排序的?
  • 理想情况下,但我不会依赖它..
  • 请注意,您的正则表达式会留下一堆(我认为不必要的)引号,并且您的代码不会捕获 id2:"C" 对,因为数据中的一个位置存在流氓空间。请参阅我的答案以解决这些问题。
  • 嗨,Brionius,实际上我需要引号。我假设的空间是一个错字,但在我的情况下本质上不是问题:)

标签: python regex regex-group


【解决方案1】:

您可以遍历findall() 结果并将它们收集到collections.defaultdict object 中。请调整您的正则表达式以不包含引号,并添加一些空格容差:

from collections import defaultdict
import re

regex = re.compile(r'label\("([^"]*)",\s*"([^"]*)"\)')
results = defaultdict(list)

for id_, tag in regex.findall(s):
    results[id_].append(tag)

print results.items()

如果您想要的只是唯一值,您可以将 list 替换为 set,并将 append() 替换为 add()

演示:

>>> from collections import defaultdict
>>> import re
>>> s = 'label("id1","A") label("id1","B") label("id2", "C") label("id2","A") label("id2","D") label("id3","A")'
>>> regex = re.compile(r'label\("([^"]*)",\s*"([^"]*)"\)')
>>> results = defaultdict(list)
>>> for id_, tag in regex.findall(s):
...     results[id_].append(tag)
... 
>>> results.items()
[('id2', ['C', 'A', 'D']), ('id3', ['A']), ('id1', ['A', 'B'])]

如果需要,您也可以对结果进行排序。

【讨论】:

    【解决方案2】:

    你得到的结果是否可以接受后处理?

    如果是这样,

    import re
    # edited your regex to get rid of the extra quotes, and to allow for the possible space that occurs in label("id2", "C")
    regex = re.compile(r'label\(\"(\S*)\",\ ?\"(\S*)\"\)')
    results = re.findall(regex,s)
    resultDict = {}
    for id, val in results:
        if id in resultDict:
            resultDict[id].append(val)
        else:
            resultDict[id] = [val]
    
    # if you really want a list of tuples rather than a dictionary:
    resultList = resultDict.items()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 2013-10-19
      相关资源
      最近更新 更多