Ich habe eine Liste von Booleschen:

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

Und ich suche nach einer Möglichkeit, die Anzahl von True in der Liste zu zählen (im obigen Beispiel möchte ich, dass die Rückgabe 3 ist.) Ich habe Beispiele für die Suche nach der Anzahl von gefunden Vorkommen bestimmter Elemente, aber gibt es eine effizientere Möglichkeit, dies zu tun, da ich mit Booleschen Werten arbeite? Ich denke an etwas Analoges zu all oder any.

167
acs 7 Okt. 2012 im 07:12

8 Antworten

Beste Antwort

True ist gleich 1.

>>> sum([True, True, False, False, False, True])
3
190
Ignacio Vazquez-Abrams 7 Okt. 2012 im 03:13

Sie können sum() verwenden:

>>> sum([True, True, False, False, False, True])
3
9
Blender 7 Okt. 2012 im 03:14

Wenn Sie sich nur mit der Konstante True befassen, ist eine einfache sum in Ordnung. Beachten Sie jedoch, dass in Python auch andere Werte als True ausgewertet werden. Eine robustere Lösung wäre die Verwendung des integrierten bool:

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

UPDATE: Hier ist eine weitere ähnlich robuste Lösung, die den Vorteil hat, transparenter zu sein:

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

P.S. Python-Trivia: True könnte wahr sein, ohne 1 zu sein. Warnung: Versuchen Sie dies nicht bei der Arbeit!

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

Viel böser:

True = False
39
Ned Deily 7 Okt. 2012 im 20:40

Nachdem ich alle Antworten und Kommentare zu dieser Frage gelesen hatte, dachte ich an ein kleines Experiment.

Ich habe 50.000 zufällige Boolesche Werte generiert und sum und count aufgerufen.

Hier sind meine Ergebnisse:

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

Nur um sicher zu gehen, habe ich es noch mehrmals wiederholt:

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

Und wie Sie sehen können, ist count dreimal schneller als sum. Daher würde ich vorschlagen, count wie in count_it zu verwenden.

Python-Version: 3.6.7
CPU-Kerne: 4
RAM-Größe: 16 GB
Betriebssystem: Ubuntu 18.04.1 LTS

4
leopal 12 Dez. 2018 im 15:27

Nur der Vollständigkeit halber (sum ist normalerweise vorzuziehen) wollte ich erwähnen, dass wir auch filter verwenden können, um die Wahrheitswerte zu erhalten. Im Normalfall akzeptiert filter eine Funktion als erstes Argument, aber wenn Sie sie None übergeben, wird nach allen "wahrheitsgemäßen" Werten gefiltert. Diese Funktion ist etwas überraschend, aber gut dokumentiert und funktioniert sowohl in Python 2 als auch in Python 3.

Der Unterschied zwischen den Versionen besteht darin, dass in Python 2 filter eine Liste zurückgibt, sodass wir len verwenden können:

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

In Python 3 gibt filter jedoch einen Iterator zurück, sodass wir len nicht verwenden können. Wenn wir die Verwendung von sum (aus irgendeinem Grund) vermeiden möchten, müssen wir auf die Konvertierung von zurückgreifen Iterator zu einer Liste (was dies viel weniger hübsch macht):

>>> 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 14 März 2016 im 18:31

Es ist sicherer, zuerst bool zu durchlaufen. Dies ist einfach zu bewerkstelligen:

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

Dann fangen Sie alles, was Python als wahr oder falsch ansieht, im entsprechenden Bucket auf:

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

Wenn Sie es vorziehen, können Sie ein Verständnis verwenden:

>>> allFalse=['',[],{},False,0,set(),(), not True, True-1]
>>> [bool(i) for i in allFalse]
[False, False, False, False, False, False, False, False, False]
3
user688635user688635 8 Okt. 2012 im 20:38

list hat eine count Methode:

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

Dies ist tatsächlich effizienter als sum und es ist expliziter in Bezug auf die Absicht, sodass es keinen Grund gibt, sum zu verwenden:

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)
133
user2357112 supports Monica 20 Dez. 2018 im 20:47

Ich bevorzuge len([b for b in boollist if b is True]) (oder das Äquivalent zum Generatorausdruck), da es ziemlich selbsterklärend ist. Weniger "magisch" als die Antwort von Ignacio Vazquez-Abrams.

Alternativ können Sie dies tun, wobei weiterhin davon ausgegangen wird, dass bool in int konvertierbar ist, jedoch keine Annahmen über den Wert von True getroffen werden: ntrue = sum(boollist) / int(True)

1
kampu 8 Okt. 2012 im 06:42