使用re.findall捕获正则表达式中的命名组

时间:2014-09-02 17:24:22

标签: python regex findall

当我试图回答这个问题时:regex to split %ages and values in python我注意到我必须从findall的结果重新排序组。例如:

data = """34% passed 23% failed 46% deferred"""
result = {key:value for value, key in re.findall('(\w+)%\s(\w+)', data)}
print(result)
>>> {'failed': '23', 'passed': '34', 'deferred': '46'}

这里findall的结果是:

>>> re.findall('(\w+)%\s(\w+)', data)
>>> [('34', 'passed'), ('23', 'failed'), ('46', 'deferred')]

有没有办法更改/指定使 re.findall返回的组的顺序:

[('passed', '34'), ('failed', '23'), ('deferred', '46')]

只是澄清一下,问题是:

是否可以指定订单或重新排序组以返回re.findall函数?

我使用上面的示例创建了一个字典,以便在您想要更改顺序时使用原因/用例(将键作为值和值作为键)

进一步澄清:

为了处理更大更复杂的正则表达式中的组,您可以命名组,但只有在执行re.search pr re.match时才能访问这些名称。根据我的阅读,findall对元组中返回的组有一个固定的索引,问题是任何人都知道如何修改这些索引。这有助于简化和直观地处理小组。

3 个答案:

答案 0 :(得分:7)

根据OP在this comment中的意图进一步澄清,取3,

Ashwin是正确的,findall不保留命名捕获组(例如(?P<name>regex))。 finditer救援!它逐个返回各个匹配对象。简单的例子:

data = """34% passed 23% failed 46% deferred"""
for m in re.finditer('(?P<percentage>\w+)%\s(?P<word>\w+)', data):
    print( m.group('percentage'), m.group('word') )

答案 1 :(得分:0)

正如您在第二个示例中指出的那样,re.findall会按原始顺序返回组。

问题是标准Python dict类型不以任何方式保留键的顺序。这是Python 2.x的手册,它使其明确,但在Python 3.x中仍然如此:https://docs.python.org/2/library/stdtypes.html#dict.items

您应该使用的是collections.OrderedDict

from collections import OrderedDict as odict

data = """34% passed 23% failed 46% deferred"""
result = odict((key,value) for value, key in re.findall('(\w+)%\s(\w+)', data))
print(result)
>>> OrderedDict([('passed', '34'), ('failed', '23'), ('deferred', '46')])

请注意,必须使用成对构造函数形式(dict((k,v) for k,v in ...)而不是dict理解构造函数({k:v for k,v in ...})。这是因为后者构造dict类型的实例,在不丢失键的顺序的情况下无法转换为OrderedDict ...这当然是你想要保留的第一名。

答案 2 :(得分:0)

Per the OP's comment on my first answer:如果你只是想重新排序这样的2元组列表:

[('34', 'passed'), ('23', 'failed'), ('46', 'deferred')]

......看起来像这样,个别元素反转:

[('passed', '34'), ('failed', '23'), ('deferred', '46')]

这是一个简单的解决方案:使用带有切片语法sequence[::-1]的列表推导来反转单个元组元素的顺序:

a = [('34', 'passed'), ('23', 'failed'), ('46', 'deferred')]
b = [x[::-1] for x in a]
print b