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
marca tolonen
list
tiene un count
método:
>>> [True,True,False].count(True)
2
Esto es en realidad más eficiente que sum
ademá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 queTrue
oFalse
.–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) mientrascount
no es.– Simplemente hermoso arte
27 de noviembre de 2020 a las 3:00
Ned Deily
Si solo te preocupa la constante True
un 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 paraTrue
. Ver docs.python.org/py3k/library/stdtypes.html#truth. losTrue = 2
fue solo para reforzar que el concepto de “verdadero” es más complejo; con un poco de código extra (es decir, usandobool()
) 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
yFalse
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
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
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 len
y 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]