这个python代码可以用列表理解来表达吗?

这个python代码可以用列表理解来表达吗?,python,list,list-comprehension,Python,List,List Comprehension,我发现下面的内容非常可读,但我想知道他们是否是一种更具蟒蛇风格的方式来完成它——也许是一种列表理解 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.ma

我发现下面的内容非常可读,但我想知道他们是否是一种更具蟒蛇风格的方式来完成它——也许是一种列表理解

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.matchkey两次,就无法直接将其作为单个列表理解编写-即

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
[pattern.match(key) for key in cgi_keys if pattern.match(key)]
但是,通过使用生成器跳过“无”元素,可以稍微移动对象:

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))]
它更短但仍然有效,因为第一个矫揉造作是一个生成器,其值在第二个语句之前不会被计算

此外,您还可以使用:

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))]
当地图返回一个生成器时。您必须在Python2中使用。ifilter也是如此


请注意,如果cgi_键非常小,您也可以在Python2中使用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]

事实上,@unutbu只是证明了这是可以做到的,但这是以额外的工作为代价的,并没有真正帮助理解代码。另一个公式使用嵌套列表理解:[match.groups for match in[pattern.matchkey for key in cgi_keys]if match]@chucksmash yes,这实际上是我在iPython中尝试的方式,但我不建议任何人在生产代码中使用这种符号。它不会改变代码的效率,但会严重影响可读性。有些人甚至称之为“不理解列表”。这一点很好!我是个傻瓜有办法吗?输入问题。快乐地走下去太容易了,从不停下来问更重要的问题,但我们应该吗?地图版本不会从pattern.match中过滤出无结果,因此,它与AttributeError断开:“非类型”对象没有属性“组”。@lvl我确实忘记了在过滤器/ifilter调用中添加。我应该添加一个名称中可以有下划线的测试用例,如在“_George_Costanza___total_flake->['George_Costanza',total_flake',”中,否则拆分将是我的第一选择。@Jamie Ha!我喜欢乔治·卡斯坦萨的全雪花!尽管我认为使用正则表达式会更好,但您的测试用例可以使用[[v[1:]来解决,如果v[0]是“u”,则在cgi中用v表示v。在cgi_u键中用split“u]”表示cgi。