2012-10-07 56 views
74

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

[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 resultado sea 3.) He encontrado ejemplos de buscar el número de apariciones de elementos específicos, pero ¿hay alguna forma más eficiente de hacerlo ya que estoy trabajando con Booleanos? Estoy pensando en algo similar a all o any.

+0

Me gusta si recuerda cómo se realizó el conteo de bits en el hardware utilizando únicamente el ensamblador. –

Respuesta

108

True es igual a 1.

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

Eso no es idiomático y hace "abuso" del tipo de coacción de bool. –

+15

@Jan Segre, no hay coacción, bool es un tipo entero. –

+13

@ panda-34, he comprobado y 'issubclass (bool, int)' de hecho se mantiene, por lo que no hay coacción. –

6

Puede utilizar sum():

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

Si sólo está preocupado por la constante True, un simple sum está muy 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 el uso de la orden interna bool:

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

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

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

P. S. Python trivia: Truepodría ser cierto 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 

mal Mucho más:

True = False 
+0

Ok, veo tu ejemplo, y veo lo que está haciendo. Además de la LOL-ness de eso, ¿hay realmente una buena razón para hacer lo que has mostrado aquí? – acs

+0

Sí, para la parte superior. Como indiqué, la prueba de Python para un "verdadero" (como en una declaración 'if') es más complicada que simplemente probar para 'Verdadero'. Consulte http://docs.python.org/py3k/library/stdtypes.html#truth. El 'True = 2' fue solo para reforzar que el concepto de" verdadero "es más complejo; con un poco de código adicional (es decir, usando 'bool()') puede hacer que la solución sea más robusta y más general. –

+7

En Python 3, 'True' y' False' son palabras clave y no puede cambiarlas. – ThePiercingPrince

1

prefiero len([b for b in boollist if b is True]) (o el generador de expresión equivalente), ya que es bastante explica por sí mismo. Menos 'mágico' que la respuesta propuesta por Ignacio Vázquez-Abrams.

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

+0

Su solución tiene al menos dos problemas. Uno, sufre del mismo problema de robustez; que podrías corregir simplemente cambiando la prueba a 'si b'. Pero, lo que es más importante, está construyendo una lista desechable que requiere que todos los valores estén en la memoria a la vez y no puede usar 'len' con una expresión de generador. Es mejor evitar tales prácticas para que la solución pueda escalar. –

+0

@Ned Deily: 'si b' es exactamente incorrecto. Solo sería correcto si la pregunta fuera sobre elementos que se evalúan como True, en lugar de verdaderos booleanos. Tomo tu segundo punto sin embargo. En ese caso, existe la variante 'sum (1 si b es True else 0 para b en boollist)'. – kampu

+0

Como señalé en otro lugar, no me queda claro si el OP realmente significa contar solo objetos de tipo bool con el valor 1 o significa el conjunto de valores más grande y generalmente más útil que evalúa verdadero. Si lo primero, entonces una prueba de identidad es el enfoque correcto, pero también es limitante. De todos modos, los objetos de tipo bool son patos bastante extraños en Python, una adición relativamente reciente al lenguaje. En cualquier caso, iría por el más simple: 'suma (1 para b en boollist si b es True)' –

73

list tiene un método count:

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

No puedo contar los valores falsos si hay 0 valor también – Kostanos

+2

No puede usar 'sum' del Otra respuesta si tiene otros valores "verdaderos" además de 1 o Verdadero. Además, la pregunta no mencionaba nada más que 'True' o' False'. –

2

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

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

A continuación, se captura todo lo que Python considera verdadero o falso en el cubo correspondiente:

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

Solo para completar (generalmente es preferible sum), quería mencionar que también podemos usar filter para obtener los valores verdaderos.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 documentado y funciona tanto en Python 2 y 3.

La diferencia entre las versiones, es que en Python 2 filter devuelve una lista, por lo que podemos utilizar 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 de sum (por alguna razón) necesitamos recurrir a la conversión del iterador a una lista (lo que hace que esto sea mucho menos) bonita):

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