我发现以下内容完全可读,但是想知道它们是否是一种更加pythonesque的方式来实现它(也许是一个列表理解)?
import re
cgi_keys = [ '_None___total', '_George___total', 'Greg__total', '_Geoff___total', '_Gillian_total' ]
pattern = re.compile(r"_(.+)___(.+)")
totals = []
for key in cgi_keys:
m = pattern.match(key)
if m:
totals.append(m.groups())
totals
将显示:
[('None', 'total'), ('George', 'total'), ('Geoff', 'total')]
但是我希望我能找到一种方法来使用如下构造来获得上述内容:
[key for key in cgi_keys if pattern.match(key)]
以不太有用的形式显示字符串:
['_None___total', '_George___total', '_Geoff___total']
这是否值得尝试将已过滤的字符串分解为元组或列表作为列表理解?
答案 0 :(得分:2)
这不能直接写为(单个)列表理解而不会为每个元素调用pattern.match(key)
两次 - 即
[pattern.match(key) for key in cgi_keys if pattern.match(key)]
但是,您可以使用生成器跳过None
元素来移动一些东西:
def skip_none(iter):
return (i for i in iter if i is not None)
totals = skip_none(pattern.match(key) for key in cgi_keys)
答案 1 :(得分:2)
实际上你可以使用:
totals = (pattern.match(key) for key in cgi_keys)
totals = [match.groups() for match in totals if match]
哪个更短但仍然有效,因为第一个影响是一个生成器,其值不会被评估,直到第二个语句。
另外,您可以使用:
totals = [match.groups for match in filter(None, map(pattern.match, cgi_keys))]
当map()
给出一个发电机。您必须在Python 2中使用imap
。同样适用于ifilter
。
请注意,如果cgi_keys
非常小,您也可以在Python 2中使用map
,因为通过迭代两次完成的额外工作无论如何都可能无法察觉。
答案 2 :(得分:0)
您可以在没有正则表达式的情况下执行此操作,并获取列表而不是元组列表。
[[v for v in cgi.split('_') if v] for cgi in cgi_keys]
结果:
[['None', 'total'], ['George', 'total'], ['Greg', 'total'], ['Geoff', 'total'], ['Gillian', 'total']]
但如果你需要元组:
[tuple([v for v in cgi.split('_') if v]) for cgi in cgi_keys]