web-dev-qa-db-ja.com

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

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

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

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

121
acs

True1と同じです。

>>> sum([True, True, False, False, False, True])
3
170

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)
113
Mark Tolonen

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

追伸Python雑学:Truecould 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
39
Ned Deily

sum()を使用できます:

>>> sum([True, True, False, False, False, True])
3
6
Blender

完全を期すために(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
5
yoniLavi

最初に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]
3
user688635

len([b for b in boollist if b is True])(またはgenerator-expressionの同等物)の方が好みです。 Ignacio Vazquez-Abramsが提案した答えよりも「魔法的」ではありません。

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

1
kampu

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

50,000個のランダムなブール値を生成し、sumcountを呼び出しました。

私の結果は次のとおりです。

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

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

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

1
GMishx