100

膨大な数のアイテムを含むリストがあると仮定すると、

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

そのリストからアイテムが特定の条件を満たすアイテムの数を取得したい。私の最初の考えは:

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

しかし、フィルタリングされたリストにも多数のアイテムがある場合、フィルタリングされた結果に対して新しいリストを作成するのはメモリの無駄だと思います。効率のために、IMHO、上記の呼び出しは以下よりも優れていることはありません。

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

一時的なリストを生成せずに条件を満たすアイテムの数を取得する機能的な方法はありますか?

4

5 に答える 5

124

ジェネレータ式を使用できます:

>>> 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
于 2013-03-13T00:54:15.203 に答える
29

ここでは、リストではなくジェネレータ内包表記が必要です。

例えば、

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

この手法の優れた点は、最終結果が評価されるまで評価とメモリへの格納を強制することなく、コード内で概念的に個別のステップを指定できることです。

于 2013-03-13T00:53:58.810 に答える
9

次のようなことができます:

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

条件を満たす要素ごとに 1 を追加するだけです。

于 2013-03-13T00:58:07.933 に答える
2
from itertools import imap
sum(imap(my_condition, l))
于 2013-03-13T00:56:27.027 に答える