Contar el número de valores booleanos verdaderos en una lista de Python

6 minutos de lectura

avatar de usuario
ac

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 (entonces, en el ejemplo anterior, quiero que el retorno sea 3.) He encontrado ejemplos de buscar el número de ocurrencias de elementos específicos, pero ¿hay una forma más eficiente de hacerlo ya que estoy trabajando con valores booleanos? Estoy pensando en algo similar a all o any.

True es igual a 1.

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

  • Eso no es idiomático y hace “abuso” del tipo coerción de bool.

    – Jan Segre

    4 sep 2014 a las 22:19

  • @Jan Segre, no hay coerción, bool es de tipo entero.

    – panda-34

    2 de marzo de 2016 a las 17:28

  • @ panda-34, revisé y issubclass(bool, int) de hecho se cumple, por lo que no hay coerción.

    – Jan Segre

    10/03/2016 a las 20:30

avatar de usuario
marca tolonen

list tiene un count método:

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

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

  • No puedo contar los valores falsos si también hay un valor 0

    – Kostanos

    20 de agosto de 2015 a las 18:55

  • no puedes usar sum de la otra respuesta si tiene otros valores “verdaderos” además de 1 o Verdadero. Además, entonces la pregunta no mencionó nada más que True o False.

    –Mark Tolonen

    06/01/2017 a las 22:05


  • Aunque no es la intención de los OP, creo que vale la pena señalar que sum funciona en otros tipos (por ejemplo, generadores) mientras count no es.

    – Simplemente hermoso arte

    27 de noviembre de 2020 a las 3:00

avatar de usuario
Ned Deily

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

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

Curiosidades de PS Python: True pudo ser verdadero sin ser 1. Advertencia: ¡no intentes 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 mal:

True = False

  • Ok, veo tu ejemplo, y veo lo que está haciendo. Aparte de lo LOL-ness, ¿hay realmente una buena razón para hacer lo que has mostrado aquí?

    – ac

    7 de octubre de 2012 a las 4:43

  • Si, para la parte de arriba. Como indiqué, la prueba de Python para un “verdadero” (como en un if declaración) es más complicado que simplemente probar para True. Ver docs.python.org/py3k/library/stdtypes.html#truth. los True = 2 fue solo para reforzar que el concepto de “verdadero” es más complejo; con un poco de código extra (es decir, usando bool()) puede hacer que la solución sea más robusta y más general.

    – Ned Deily

    7 de octubre de 2012 a las 5:03

  • En Python 3, True y False son palabras clave y no puede cambiarlas.

    – El Príncipe Perforador

    17 de agosto de 2013 a las 13:57

Puedes usar sum():

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

avatar de usuario
Vasudev Maduri

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

Generé 50,000 booleanos aleatorios y llamé sum y count en 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 puedes ver, count es 3 veces más rápido que sum. Así que sugeriría usar count como lo hice en count_it.

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

avatar de usuario
yoniLavi

Solo por el bien de la integridad (sum suele ser preferible), quería mencionar que también podemos usar filter para obtener los valores veraces. En el caso habitual, filter acepta una función como primer argumento, pero si la pasa None, filtrará todos los valores de “veracidad”. 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 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, filter devuelve un iterador, por lo que no podemos usar leny si queremos evitar el uso 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)
<builtins.filter at 0x7f64feba5710>
>>> list(filter(None, bool_list))
[True, True, True]
>>> len(list(filter(None, bool_list)))
3

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

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

Luego, captará todo lo que Python considere Verdadero o Falso en el depósito 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 prefiere, puede 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]

¿Ha sido útil esta solución?