Pythonリスト内の真のブール値の数を数える


152

ブール値のリストがあります:

[True, True, False, False, False, True]

Trueリスト内の数を数える方法を探しています(上の例では、戻り値をにしたいので3。)特定の要素の発生数を探す例を見つけましたが、もっと私はブール値で作業しているので、それを行う効率的な方法は?allまたはに類似したものを考えていanyます。


アセンブラのみを使用してハードウェアでビットカウントがどのように行われたかを覚えているように。
Vladislavs Dovgalecs 2017年

回答:



152

list持っているcount方法を:

>>> [True,True,False].count(True)
2

これは実際には、よりも効率的でありsum、インテントについてより明確であるため、使用する理由はありませんsum

In [1]: import random

In [2]: x = [random.choice([True, False]) for i in range(100)]

In [3]: %timeit x.count(True)
970 ns ± 41.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [4]: %timeit sum(x)
1.72 µs ± 161 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

2
0の値もある場合、False値をカウントできません
コスタノス

10
sum1またはTrue以外の「true」値がある場合、他の回答を使用することはできません。その上、それから質問は何もTrueまたは何も言及しませんでしたFalse
Mark Tolonen 2017年

43

定数のみに関心がある場合Trueは、単純な方法sumで問題ありません。ただし、Pythonでは他の値も評価されることに注意しTrueてください。より堅牢なソリューションは、bool組み込みを使用することです:

>>> l = [1, 2, True, False]
>>> sum(bool(x) for x in l)
3

更新:より透明性が高いという利点を持つ、同様に堅牢な別のソリューションを次に示します。

>>> sum(1 for x in l if x)
3

PS Pythonトリビア:1でなくても本当であるTrue 可能性があります。警告:職場でこれを試さないでください!

>>> True = 2
>>> if True: print('true')
... 
true
>>> l = [True, True, False, True]
>>> sum(l)
6
>>> sum(bool(x) for x in l)
3
>>> sum(1 for x in l if x)
3

はるかに悪:

True = False

わかりました、あなたの例を見て、私はそれが何をしているのかを見ます。それの笑い以外に、あなたがここで示したことをする正当な理由は実際にありますか?
acs

1
はい、上部についてです。既にif述べたように、「ステートメント」のような「true」のPythonテストは、単なるのテストよりも複雑ですTruedocs.python.org/py3k/library/stdtypes.html#truthをご覧ください。これTrue = 2は、「真」の概念がより複雑であることを強調するためだけのものでした。少し余分なコード(つまりを使用bool())を使用すると、ソリューションをより堅牢でより一般的なものにすることができます。
Ned Deily

9
Python 3ではTrueFalseキーワードであり、変更することはできません。
ThePiercingPrince 2013


5

完全を期すために(sum通常は望ましい)、filter真実の値を取得するためにも使用できることを述べておきたいと思います。通常の場合、filterは最初の引数として関数を受け入れますがNone、それを渡すと、すべての「真の」値をフィルタリングします。この機能は多少意外ですが、十分に文書化されており、Python 2と3の両方で機能します。

バージョン間の違いは、Python 2 filterではリストが返されるため、次のように使用できることlenです。

>>> bool_list = [True, True, False, False, False, True]
>>> filter(None, bool_list)
[True, True, True]
>>> len(filter(None, bool_list))
3

しかし、Python 3ではfilterイテレータが返されるため、を使用できません。(何らかの理由で)len使用を避けたい場合はsum、イテレータをリストに変換する必要があります(これにより、かなり美しくなくなります)。

>>> bool_list = [True, True, False, False, False, True]
>>> filter(None, bool_list)
<builtins.filter at 0x7f64feba5710>
>>> list(filter(None, bool_list))
[True, True, True]
>>> len(list(filter(None, bool_list)))
3

4

この質問に対するすべての回答とコメントを読んだ後、ちょっとした実験をしようと思いました。

私は50,000のランダムなブール値を生成し、呼ばれるsumと、countそれらの上に。

これが私の結果です:

>>> a = [bool(random.getrandbits(1)) for x in range(50000)]
>>> len(a)
50000
>>> a.count(False)
24884
>>> a.count(True)
25116
>>> def count_it(a):
...   curr = time.time()
...   counting = a.count(True)
...   print("Count it = " + str(time.time() - curr))
...   return counting
... 
>>> def sum_it(a):
...   curr = time.time()
...   counting = sum(a)
...   print("Sum it = " + str(time.time() - curr))
...   return counting
... 
>>> count_it(a)
Count it = 0.00121307373046875
25015
>>> sum_it(a)
Sum it = 0.004102230072021484
25015

念のため、さらに何回か繰り返しました。

>>> count_it(a)
Count it = 0.0013530254364013672
25015
>>> count_it(a)
Count it = 0.0014507770538330078
25015
>>> count_it(a)
Count it = 0.0013344287872314453
25015
>>> sum_it(a)
Sum it = 0.003480195999145508
25015
>>> sum_it(a)
Sum it = 0.0035257339477539062
25015
>>> sum_it(a)
Sum it = 0.003350496292114258
25015
>>> sum_it(a)
Sum it = 0.003744363784790039
25015

ご覧のとおり、countはの3倍の速度ですsum。私が使用することをお勧めしますので、count私が行ったようにcount_it

Pythonバージョン:3.6.7
CPUコア:4
RAMサイズ:16 GB
OS:Ubuntu 18.04.1 LTS


3

bool最初に実行する方が安全です。これは簡単に行えます:

>>> sum(map(bool,[True, True, False, False, False, True]))
3

次に、PythonがTrueまたはFalseと見なすすべてを適切なバケットにキャッチします。

>>> allTrue=[True, not False, True+1,'0', ' ', 1, [0], {0:0}, set([0])]
>>> list(map(bool,allTrue))
[True, True, True, True, True, True, True, True, True]

必要に応じて、理解度を使用できます。

>>> allFalse=['',[],{},False,0,set(),(), not True, True-1]
>>> [bool(i) for i in allFalse]
[False, False, False, False, False, False, False, False, False]

1

len([b for b in boollist if b is True])自明ですので、私は(またはジェネレータ式の同等物)を好みます。Ignacio Vazquez-Abramsによって提案された答えよりも「魔法」が少ない。

または、これを行うこともできます。これは、boolがintに変換可能であると想定していますが、Trueの値については想定していません。 ntrue = sum(boollist) / int(True)


ソリューションには少なくとも2つの問題があります。1つは、同じ堅牢性の問題があることです。テストをに変更するだけで修正できます if b。ただし、さらに重要なことは、すべての値を一度にメモリに格納する必要がある使い捨てリストを作成lenしているため、ジェネレーター式で使用できないことです。ソリューションを拡張できるように、このようなプラクティスを回避することをお勧めします。
Ned Deily

@ネッドデイリー:if b間違いです。質問が、実際のTrueブール値ではなく、Trueと評価される項目に関するものである場合にのみ、それは正しいでしょう。私はあなたの2番目の点を取ります。その場合、バリアントがありsum(1 if b is True else 0 for b in boollist)ます。
kampu

他の場所で述べたように、OPが実際に値1のbool型のオブジェクトのみをカウントすることを意味するのか、それともtrueと評価するより大きく一般的に有用な値のセットを意味するのかは、私にはわかりません。前者の場合、アイデンティティテストは適切なアプローチですが、制限もあります。とにかく、bool型のオブジェクトは、Pythonのかなり奇妙なアヒルであり、比較的最近になって言語に追加されました。いずれにせよ、私はもっと単純なsum(1 for b in boollist if b is True)
方法をとり
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.