python:特定の条件でリスト(シーケンス)からアイテムの数を取得します


84

膨大な数のアイテムのリストがあると仮定します。

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

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

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

しかし、my_condition()でフィルタリングされたリストにも多数のアイテムがある場合、フィルタリングされた結果の新しいリストを作成することは、メモリの浪費にすぎないと思います。効率のために、私見、上記の呼び出しは以下よりも優れていることはできません:

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

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

前もって感謝します。


3
ジェネレータとリストの間の選択は、実行時間とメモリ消費の間の選択です。コードをプロファイリングすると、結果が直感に反することがどれほど頻繁にあるかに驚かれることでしょう。時期尚早の最適化はすべての悪の根源です。
Paulo Scardine 2013年

回答:


102

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

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

これは、という事実を使用していint(True) == 1ます。

または、itertools.imap(python 2)または単にmap(python 3)を使用することもできます。

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

1
@mgilson:その計算が行われることはないと思います-startデフォルトは0なので、最初の加算はTrue + 0、いいえ?
DSM

4
はい。多分私はもっと明確にすべきです...それは何であるかint(True)は関係ありません。 int("1") == 1また、しかしそれはあなたができるという意味ではありません"1" + 0。重要なのは、Pythonがどのように評価するinteger + Trueinteger + Falseです。
mgilson 2013年

2
@mgilson:うーん、わかりました、あなたは私を納得させました。
DSM

4
重要なのは、boolとのサブクラスであるintため、boolとintを簡単に追加できます(True値が1でFalse値が0の場合)。
mgilson 2013年

さて、それは私が言及することによって得ていたものですがint(True) == 1int("1") == 1それをそのように省略したことを証明するあなたのポイントは、真実ではないことを意味する可能性があります。
DSM

21

ここにリストするのではなく、ジェネレーターの理解が必要です。

例えば、

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

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


10

reduce関数型プログラミングが必要な場合は、これを使用して行うこともできます。

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

この方法では、1回のパスのみを実行し、中間リストは生成されません。


7

あなたは次のようなことをすることができます:

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

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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.