我与列表理解有一种爱/恨的关系。一方面我认为它们整洁优雅。另一方面,我讨厌阅读它们。 (特别是那些我没写的)我通常遵循规则,让它可读,直到需要速度。所以我的问题在这一点上确实是学术性的。
我想要一张表中的电台列表,这些电台的字符串通常有额外的空格。我需要剥掉那些空间。有时这些电台是空白的,不应包括在内。
stations = []
for row in data:
if row.strip():
stations.append(row.strip())
这转换为此列表理解:
stations = [row.strip() for row in data if row.strip()]
这种方法运作得很好,但我发现我正在做两次剥离。我猜测.strip()实际上并不需要两次,并且通常比分配变量慢
stations = []
for row in data:
blah = row.strip()
if blah:
stations.append(blah)
原来我是对的。
> Striptwice list comp 14.5714301669
> Striptwice loop 17.9919670399
> Striponce loop 13.0950567955
Timeit显示两个循环段之间,第二个(条带一次)更快。这里没有真正的惊喜。令我感到惊讶的是,列表理解只是稍微慢一点,即使它正在进行两次剥离。
我的问题:有没有办法编写一个只执行一次的列表理解?
的结果:
以下是建议的时间结果
# @JonClements & @ErikAllik
> Striptonce list comp 10.7998494348
# @adhie
> Mapmethod loop 14.4501044569
答案 0 :(得分:29)
首先创建一个剥离字符串的生成器,然后使用:
stations = [row for row in (row.strip() for row in data) if row]
您也可以在没有comp的情况下编写它,例如(交换到imap
并删除Python {x的list
):
stations = list(filter(None, map(str.strip, data)))
答案 1 :(得分:13)
嵌套的理解可能很难阅读,所以我的第一个偏好是:
stripped = (x.strip() for x in data)
stations = [x for x in stripped if x]
或者,如果你内联stripped
,你会得到一个(嵌套的)列表理解:
stations = [x for x in (x.strip() for x in data) if x]
请注意,第一个/内部理解是一个实际的生成器表达式,换句话说,它是一个惰性列表理解;这是为了避免迭代两次。
答案 2 :(得分:1)
使用map()将strip应用于所有元素,然后过滤。
[item for item in map(lambda x: x.strip(), list) if item]