使用正则表达式过滤数据列表的Pythonic方法?

时间:2015-02-13 15:42:49

标签: python regex list-comprehension

我有一个字符串列表,我希望使用正则表达式进行过滤。我有一个解决方案的开端:

lines = ['Some data', 'Data of interest', 'Some data', 'Data of Interest', 'Some data', 'Data of interest']
r = re.compile(r'.*[iI]nterest.*')
relevant_lines = [r.findall(line) for line in lines]
print(relevant_lines)

......几乎有效:

[[], ['Data of interest'], [], ['Data of Interest'], [], ['Data of interest']]

...但是有没有办法只用匹配和没有嵌套列表的行填充结果列表?

编辑 - 是否有比以下更简洁的方法?

[r[0] for r in [r.findall(line) for line in lines] if len(r) > 0]

2 个答案:

答案 0 :(得分:2)

只需使用普通循环,并非所有内容都适合列表comp:

r = re.compile(r'.*[iI]nterest.*')
relevant_lines = []
for line in lines:
    mtch = r.match(line)
    if mtch:
        relevant_lines.append(mtch.group())

如果你使用列表comp,生成器表达式和过滤空列表会更好:

relevant_lines = filter(None,(r.findall(line) for line in lines))

或者确实使用匹配进行过滤:

[x.group() for x in filter(None,(r.match(line) for line in lines))]

for python2使用itertools.ifilter

或者更方便的方法切换itertools.imap的地图并使用python2过滤ifilter

[x.group() for x in filter(None, map(r.match, lines))]

您可以使用内部循环的生成器表达式重写您自己的列表comp:

[r[0] for r in (r.findall(line) for line in lines) if r]

如果您不需要列表,请使用生成器表达式并迭代它。

答案 1 :(得分:1)

relevant_lines = [m.group(0) for m in map(r.match, lines) if m is not None]

这是控制台的结果:

>>> import re
>>> lines = ['Some data', 'Data of interest', 'Some data', 'Data of Interest', 'Some data', 'Data of interest']
>>> r = re.compile(r'.*[iI]nterest.*')
>>> relevant_lines = [m.group(0) for m in map(r.match, lines) if m is not None]
>>> relevant_lines
['Data of interest', 'Data of Interest', 'Data of interest']
事情并不复杂。将函数式编程与生成器结合起来非常好。