获取符合条件的列表(或其他可迭代对象)项数

120 投票
5 回答
108643 浏览
提问于 2025-04-17 18:53

假设我有一个包含很多项目的列表,

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

有没有什么方法可以在不生成临时列表的情况下,直接获取满足条件的项目数量呢?

5 个回答

13

如果你喜欢函数式编程的话,也可以用 reduce 来实现这个功能。

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

这样做的话,你只需要遍历一次,不会产生中间的列表。

32

你在这里想要的是一个生成器表达式,而不是一个列表。

举个例子,

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(不过我觉得明确的列表和生成器表达式看起来更符合Python的风格)。

需要注意的是,虽然在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

这个技巧的好处在于,你可以在代码中指定概念上独立的步骤,而不需要在最终结果计算之前就强制进行计算和存储在内存中。

152

你可以使用一个生成器表达式

>>> 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

这利用了一个事实:True == 1False == 0

另外,你也可以使用itertools.imap(在python 2中)或者直接使用map(在python 3中):

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

撰写回答