15

我对列表理解有爱/恨的关系。一方面,我认为它们整洁而优雅。另一方面,我讨厌阅读它们。(尤其是我没有写的)我通常遵循以下规则,使其可读,直到需要速度。所以我的问题在这一点上真的很学术。

我想要一张表中的电台列表,这些电台的字符串通常有额外的空格。我需要去掉那些空间。有时这些电台是空白的,不应包括在内。

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
4

3 回答 3

29

有 - 首先创建一个剥离字符串的生成器,然后使用它:

stations = [row for row in (row.strip() for row in data) if row]

您也可以在没有 comp 的情况下编写它,例如(对于 Python 2.x交换imap和删除):list

stations = list(filter(None, map(str.strip, data)))
于 2013-10-04T15:35:21.957 回答
13

嵌套理解可能很难阅读,所以我的首选是:

stripped = (x.strip() for x in data)
stations = [x for x in stripped if x]

或者,如果你 inline stripped,你会得到一个(嵌套的)列表理解:

stations = [x for x in (x.strip() for x in data) if x]

请注意,第一个/内部推导实际上是一个生成器表达式,换句话说,它是一个惰性列表推导;这是为了避免重复两次。

于 2013-10-04T15:36:33.743 回答
1

使用 map() 将条带应用于所有元素,然后过滤。

[item for item in map(lambda x: x.strip(), list) if item]
于 2013-10-04T15:38:04.800 回答