从列表(或其他可迭代的)中获取具有某些条件的项的数量

假设我有一个包含大量物品的清单,

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

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

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

但是,如果过滤列表也有大量的项目,我认为 为筛选结果创建一个新列表只是浪费内存。恕我直言,就效率而言,上述呼吁不可能比:

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

有没有什么函数式的方法可以在不产生临时列表的情况下获得满足条件的项目的 # ?

95465 次浏览

You want a generator comprehension rather than a list here.

For example,

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

Or use itertools.imap (though I think the explicit list and generator expressions look somewhat more Pythonic).

Note that, though it's not obvious from the sum example, you can compose generator comprehensions nicely. For example,

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

The cool thing about this technique is that you can specify conceptually separate steps in code without forcing evaluation and storage in memory until the final result is evaluated.

You can use a generator expression:

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

or even

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

which uses the fact that True == 1 and False == 0.

Alternatively, you could use itertools.imap (python 2) or simply map (python 3):

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

you could do something like:

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

which just adds 1 for each element that satisfies the condition.

This can also be done using reduce if you prefer functional programming

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

This way you only do 1 pass and no intermediate list is generated.