2014-10-31 17 views
1

如果lst是整数的列表,我想有Haskell的Python中的列表解析“其中”

[dif for i in range(1, len(lst)) where dif = lst[i]-lst[i-1] if dif < 5] 

但很显然,绑定变量一样,在语法上不正确的(除了一个事实,即where是从Haskell借来的)。 我可以做

[dif for i in range(1, len(lst)) for dif in (lst[i]-lst[i-1],) if dif < 5] 

使差异在一个长度 - 一个可迭代。另一种选择:

[lst[i]-lst[i-1] for i in range(1, len(lst)) if lst[i]-lst[i-1] < 5] 

此外,我可以定义一个中间列表的差异,然后过滤它。但这两种选择都不是很好。是否有一个很好的单线可以拥有我想要的?

+2

Python中最好的一个是最后一个代码片段。 – 2014-10-31 19:50:45

+0

为什么一个班轮?好奇... – wwii 2014-11-01 02:58:11

+0

@wwii:并不是说它真的很重要,但是一个好的单线通常比一个更大的表达更容易理解。 – matiasg 2014-11-03 00:51:37

回答

1

你可以使用嵌套的理解与发电机的效率:

[dif for dif in (lst[i]-lst[i-1] for i in range(1, len(lst))) if dif < 5] 
+0

我喜欢这个。这是中间清单方法,但效率和单线性(?)。谢谢! – matiasg 2014-10-31 20:02:54

5

我不认为有很大的这里是1班轮。我想,因为它是一个列表,你可以用切片:

[a-b for a, b in zip(lst[1:], lst) if a-b < 5] 

这还不是最高效lst[1:]创建一个副本,zip也物化一个新的列表(上python2.x)。我们可以做一个好一点与itertools:

from itertools import izip, islice 
[a-b for a, b in izip(islice(lst, 1), lst) if a-b < 5] 

(注意,python3.x摒弃了izip,所以如果你使用python3,只需使用zip)。

+0

你可以将它与一个生成器表达式结合起来计算'a - b'一次,但我在这里看不到这一点。 – 2014-10-31 19:54:50

+0

@MartijnPieters - 是的,我考虑过这个,但是这并不能带来一个不错的1班轮。然后它是一个2班(* gasp!*)。 – mgilson 2014-10-31 19:56:33