获取符合条件的列表(或其他可迭代对象)项数
假设我有一个包含很多项目的列表,
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 == 1
和 False == 0
。
另外,你也可以使用itertools.imap
(在python 2中)或者直接使用map
(在python 3中):
>>> def my_condition(x):
... return x % 4 == 3
...
>>> sum(map(my_condition, l))
2