python:获取具有特定条件的列表(序列)中的项目数

cin*_*nsk 66 python functional-programming list count sequence

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

l = [ 1, 4, 6, 30, 2, ... ]
Run Code Online (Sandbox Code Playgroud)

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

count = len([i for i in l if my_condition(l)])
Run Code Online (Sandbox Code Playgroud)

但是如果my_condition()过滤列表也有很多项,我认为为过滤结果创建新列表只是浪费内存.为了效率,恕我直言,以上呼叫不能比:

count = 0
for i in l:
    if my_condition(l):
        count += 1
Run Code Online (Sandbox Code Playgroud)

有没有任何功能风格的方法来获得满足特定条件的项目#而不生成临时列表?

提前致谢.

DSM*_*DSM 87

您可以使用生成器表达式:

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

甚至

>>> sum(i % 4 == 3 for i in l)
2
Run Code Online (Sandbox Code Playgroud)

它使用的事实int(True) == 1.

或者,您可以使用itertools.imap(python 2)或简单地map(python 3):

>>> def my_condition(x):
...     return x % 4 == 3
... 
>>> sum(map(my_condition, l))
2
Run Code Online (Sandbox Code Playgroud)

  • 更重要的是,它使用了"True + True == 2"的事实 (4认同)
  • 是.也许我应该更清楚......`int(True)`是什么并不重要.`int("1")== 1`也,但这并不意味着你可以做"1"+ 0`.重要的是python如何评估`integer + True`或`integer + False`. (4认同)
  • 关键是`bool`是`int`的子类,你可以轻松添加bools和int(其中`True`的值为1,而'False`的值为0). (4认同)
  • @mgilson:嗯,好吧,你说服了我. (2认同)

Joh*_*hnJ 17

你想要一个生成器理解而不是列表.

例如,

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
Run Code Online (Sandbox Code Playgroud)

或者使用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
Run Code Online (Sandbox Code Playgroud)

关于这种技术的一个很酷的事情是,你可以在代码中指定概念上独立的步骤,而不必在内存中强制评估和存储,直到评估最终结果.


Jsd*_*ers 6

你可以这样做:

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

只为满足条件的每个元素添加1.


Wil*_*ill 6

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

reduce(lambda count, i: count + my_condition(i), l, 0)
Run Code Online (Sandbox Code Playgroud)

这样,您只能执行1次传递,并且不会生成任何中间列表.