Contando el número de verdaderos booleanos en una lista de Python

Tengo una lista de booleanos:

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

y estoy buscando una manera de contar el número de True en la lista (por lo que en el ejemplo anterior, quiero que el retorno sea 3 ). He encontrado ejemplos de cómo buscar el número de ocurrencias de elementos específicos, pero ¿Una forma más eficiente de hacerlo ya que estoy trabajando con booleanos? Estoy pensando en algo análogo a all o any .

True es igual a 1 .

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

list tiene un método de count :

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

Esto es en realidad más eficiente que la sum , además de ser más explícito sobre la intención, por lo que no hay razón para usar la 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) 

Si solo le interesa la constante True , una sum simple está bien. Sin embargo, tenga en cuenta que en Python otros valores también se evalúan como True . Una solución más robusta sería usar el bool builtin:

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

ACTUALIZACIÓN: Aquí hay otra solución igualmente robusta que tiene la ventaja de ser más transparente:

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

PS Python trivia: True podría ser verdad sin ser 1. Advertencia: ¡no intente esto en el trabajo!

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

Mucho más malvado:

 True = False 

Puedes usar sum() :

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

Sólo por razones de integridad (la sum suele ser preferible), quería mencionar que también podemos usar el filter para obtener los valores verdaderos. En el caso habitual, el filter acepta una función como primer argumento, pero si la pasa None , filtrará todos los valores “verdaderos”. Esta característica es algo sorprendente, pero está bien documentada y funciona tanto en Python 2 como en 3.

La diferencia entre las versiones, es que en Python 2, el filter devuelve una lista, por lo que podemos usar len :

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

Pero en Python 3, el filter devuelve un iterador, por lo que no podemos usar len , y si queremos evitar el uso de la sum (por cualquier motivo) debemos recurrir a convertir el iterador en una lista (lo que hace que esto sea mucho menos bonito) :

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

Es más seguro correr por bool primero. Esto se hace fácilmente:

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

Luego, capturará todo lo que Python considere Verdadero o Falso en el grupo apropiado:

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

Si lo prefieres, puedes utilizar una comprensión:

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

Prefiero len([b for b in boollist if b is True]) (o el equivalente de expresión-generador), ya que es bastante autoexplicativo. Menos ‘mágico’ que la respuesta propuesta por Ignacio Vázquez-Abrams.

Alternativamente, puede hacer esto, que aún asume que bool es convertible a int, pero no hace suposiciones sobre el valor de True: ntrue = sum(boollist) / int(True)

Después de leer todas las respuestas y comentarios sobre esta pregunta, pensé hacer un pequeño experimento.

Generé 50,000 booleanos al azar y llamé a la sum y count con ellos.

Aquí están mis resultados:

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

Solo para estar seguro, lo repetí varias veces más:

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

Y como puede ver, el count es 3 veces más rápido que la sum . Así que sugeriría usar count como lo hice en count_it .

Versión de Python: 3.6.7
Núcleos de la CPU: 4
Tamaño de RAM: 16 GB
SO: Ubuntu 18.04.1 LTS