使用Python列表推导计算列表中的正整数元素

fai*_*ldt 46 python integer list-comprehension sum list

我有一个整数列表,我需要计算它们中有多少是> 0.
我目前正在使用列表理解,它看起来像这样:

sum([1 for x in frequencies if x > 0])
Run Code Online (Sandbox Code Playgroud)

这似乎是一个体面的理解,但我真的不喜欢"1"; 这看起来像是一个神奇的数字.有没有更多的Python方法来做到这一点?

unu*_*tbu 77

如果要减少内存量,可以避免使用生成器生成临时列表:

sum(x > 0 for x in frequencies)
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为它bool是以下的子类int:

>>> isinstance(True,int)
True
Run Code Online (Sandbox Code Playgroud)

而且True价值是1:

>>> True==1
True
Run Code Online (Sandbox Code Playgroud)

然而,正如Joe Golton在评论中指出的那样,这个解决方案并不是很快.如果你有足够的内存来使用中间临时列表,那么......的解决方案可能会更快.以下是比较各种解决方案的一些时间:

>>> frequencies = [random.randint(0,2) for i in range(10**5)]

>>> %timeit len([x for x in frequencies if x > 0])   # sth
100 loops, best of 3: 3.93 ms per loop

>>> %timeit sum([1 for x in frequencies if x > 0])
100 loops, best of 3: 4.45 ms per loop

>>> %timeit sum(1 for x in frequencies if x > 0)
100 loops, best of 3: 6.17 ms per loop

>>> %timeit sum(x > 0 for x in frequencies)
100 loops, best of 3: 8.57 ms per loop
Run Code Online (Sandbox Code Playgroud)

请注意,timeit结果可能因Python,OS或硬件的版本而异.

当然,如果你在一大堆数字上做数学,你可能应该使用NumPy:

>>> frequencies = np.random.randint(3, size=10**5)
>>> %timeit (frequencies > 0).sum()
1000 loops, best of 3: 669 us per loop
Run Code Online (Sandbox Code Playgroud)

NumPy数组比等效的Python列表需要更少的内存,并且计算的执行速度可以比任何纯Python解决方案快得多.

  • @Peter:注意你的建议在数据上循环两次; 一次构建输出列表,两次计算True值. (3认同)
  • 变化:[x> 0表示频率为x] .count(True) (2认同)

Gre*_*ill 24

更像Pythonic的方式是使用生成器代替:

sum(1 for x in frequencies if x > 0)
Run Code Online (Sandbox Code Playgroud)

这样可以避免在调用之前生成整个列表sum().


sth*_*sth 9

您可以len()在筛选列表上使用:

len([x for x in frequencies if x > 0])
Run Code Online (Sandbox Code Playgroud)

  • 更好的是,使用发电机(带[和]) (3认同)