python:在一定条件下从列表(序列)获取项目数


80

假设我有一个包含大量项目的列表。

l = [ 1, 4, 6, 30, 2, ... ]

我想从该列表中获取项目数,其中一个项目应满足一定条件。我的第一个想法是:

count = len([i for i in l if my_condition(l)])

但是,如果my_condition()过滤列表中也包含大量项目,我认为为过滤结果创建新列表只是浪费内存。为了提高效率,恕我直言,上面的通话不能比以下更好:

count = 0
for i in l:
    if my_condition(l):
        count += 1

是否有任何功能样式的方法来获得满足特定条件的项目数而不生成临时列表?

提前致谢。


3
生成器和列表之间的选择是执行时间和内存消耗之间的选择。如果对代码进行概要分析,您会惊讶结果经常出现反直观的情况。过早的优化是万恶之源。
Paulo Scardine 2013年

Answers:


98

您可以使用生成器表达式

>>> l = [1, 3, 7, 2, 6, 8, 10]
>>> sum(1 for i in l if i % 4 == 3)
2

甚至

>>> sum(i % 4 == 3 for i in l)
2

使用事实int(True) == 1

另外,您可以使用itertools.imap(python 2)或仅使用map(python 3):

>>> def my_condition(x):
...     return x % 4 == 3
... 
>>> sum(map(my_condition, l))
2

1
@mgilson:我认为该计算从未执行过-start默认为0,所以第一个加法是True + 0,不是吗?
DSM

4
是。也许我应该更清楚一点……没关系int(True)int("1") == 1也可以,但这并不意味着您可以做"1" + 0。重要的是python如何评估integer + Trueinteger + False
mgilson 2013年

2
@mgilson:嗯,好的,你说服了我。
DSM

4
关键是那bool是您的子类,int因此您可以轻松添加布尔值和整数(True值均为1且False值为0)。
mgilson

嗯,这就是我提到的内容int(True) == 1,但是您的观点int("1") == 1证明,以这种方式缩写可能意味着不正确的事情。
DSM

19

您需要生成器理解而不是此处的列表。

例如,

l = [1, 4, 6, 7, 30, 2]

def my_condition(x):
    return x > 5 and x < 20

print sum(1 for x in l if my_condition(x))
# -> 2
print sum(1 for x in range(1000000) if my_condition(x))
# -> 14

或使用itertools.imap(尽管我认为显式列表和生成器表达式看起来更像Pythonic)。

请注意,尽管从sum示例中并不明显,但是您可以很好地构成生成器理解。例如,

inputs = xrange(1000000)      # In Python 3 and above, use range instead of xrange
odds = (x for x in inputs if x % 2)  # Pick odd numbers
sq_inc = (x**2 + 1 for x in odds)    # Square and add one
print sum(x/2 for x in sq_inc)       # Actually evaluate each one
# -> 83333333333500000

这项技术的妙处在于,您可以在代码中指定概念上分离的步骤,而无需强制评估并存储在内存中,直到评估最终结果为止。


10

reduce如果您更喜欢函数式编程,也可以使用

reduce(lambda count, i: count + my_condition(i), l, 0)

这样,您只需要进行1次通过,就不会生成任何中间列表。


7

您可以执行以下操作:

l = [1,2,3,4,5,..]
count = sum(1 for i in l if my_condition(i))

只需为满足条件的每个元素加1。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.