这个 python 代码可以用列表理解来表达吗?
Can this python code be expressed with list comprehension?
我发现以下内容完全可读,但想知道它们是否是一种更像 python 的方式来完成它(也许是列表理解)?
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']
是否值得尝试将过滤后的字符串分解为元组或列表作为列表理解?
如果不为每个元素调用 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)
实际上你可以使用:
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))]
As map()
还给了一个发电机。您必须在 Python 2 中使用 imap
。 ifilter
.
也是如此
请注意,如果 cgi_keys
真的很小,您也可以在 Python 2 中使用 map
,因为通过迭代两次完成的额外工作可能无论如何都不会被注意到。
您可以在没有正则表达式的情况下执行此操作,并获取列表列表而不是元组。
[[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]
我发现以下内容完全可读,但想知道它们是否是一种更像 python 的方式来完成它(也许是列表理解)?
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']
是否值得尝试将过滤后的字符串分解为元组或列表作为列表理解?
如果不为每个元素调用 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)
实际上你可以使用:
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))]
As map()
还给了一个发电机。您必须在 Python 2 中使用 imap
。 ifilter
.
请注意,如果 cgi_keys
真的很小,您也可以在 Python 2 中使用 map
,因为通过迭代两次完成的额外工作可能无论如何都不会被注意到。
您可以在没有正则表达式的情况下执行此操作,并获取列表列表而不是元组。
[[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]