2012-10-07 8 views
74

Ho una lista di booleane:Contando il numero di veri booleani in una lista Python

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

e sto cercando un modo per contare il numero di True nella lista (così nell'esempio di cui sopra, Voglio che il rendimento sia 3.) Ho trovato esempi di ricerca del numero di occorrenze di elementi specifici, ma c'è un modo più efficiente di farlo poiché sto lavorando con Booleans? Sto pensando a qualcosa di analogo a all o any.

+0

Come se ricordassi come è stato eseguito il conteggio dei bit nell'hardware utilizzando solo l'assembler. –

risposta

108

True è uguale a 1.

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

Non è idiomatico e fa "abuso" del tipo di coercizione del bool. –

+15

@Jan Segre, non c'è coercizione, bool è un tipo intero. –

+13

@ panda-34, ho controllato e 'issubclass (bool, int)' in effetti tiene, quindi non c'è coercizione. –

6

È possibile utilizzare sum():

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

Se siete preoccupati solo con la costante True, un semplice sum va bene. Tuttavia, tieni presente che in Python altri valori valgono anche come True. Una soluzione più robusta sarebbe usare il bool integrato:

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

UPDATE: Ecco un'altra soluzione simile robusto che ha il vantaggio di essere più trasparente:

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

P.S. Python: Truepotrebbe essere vero senza essere 1. Attenzione: non provare questo al lavoro!

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

Molto più male:

True = False 
+0

Ok, vedo il tuo esempio e vedo cosa sta facendo. A prescindere dalla LOL-ness, c'è davvero una buona ragione per fare ciò che hai mostrato qui? – acs

+0

Sì, per la parte superiore. Come ho indicato, il test di Python per un "vero" (come in un'istruzione 'if') è più complicato del semplice test per' True'. Vedi http://docs.python.org/py3k/library/stdtypes.html#truth. Il 'Vero = 2 'era solo per rinforzare il fatto che il concetto di" vero "è più complesso; con un po 'di codice in più (ad esempio usando 'bool()') puoi rendere la soluzione più robusta e più generale. –

+7

In Python 3, 'True' e' False' sono parole chiave e non è possibile cambiarle. – ThePiercingPrince

1

preferisco len([b for b in boollist if b is True]) (o il generatore di espressione equivalente), come è abbastanza auto-esplicativo. Meno "magico" della risposta proposta da Ignacio Vazquez-Abrams.

In alternativa, si può fare questo, che assume ancora che il bool è convertibile a int, ma non fa alcuna ipotesi circa il valore True: ntrue = sum(boollist)/int(True)

+0

La tua soluzione ha almeno due problemi. Uno, soffre dello stesso problema di robustezza; che puoi correggere semplicemente cambiando il test in 'if b'. Ma, cosa più importante, stai costruendo una lista di sparizione che richiede che tutti i valori siano in memoria in una volta e non puoi usare 'len' con un'espressione di generatore. Meglio evitare tali pratiche in modo che la soluzione possa ridimensionarsi. –

+0

@Ned Deily: 'se b' è esattamente sbagliato. Sarebbe corretto solo se la domanda riguardasse elementi che valutano come Veri, piuttosto che veri veri booleani. Prendo il tuo secondo punto però. In questo caso c'è la variante 'sum (1 se b è True else 0 per b in boollist)'. – kampu

+0

Come ho notato altrove, non mi è chiaro dalla domanda se l'OP significhi davvero contare solo oggetti di tipo bool con il valore 1 o che significhi il più ampio e generalmente più utile insieme di valori che valuti true. Se il primo, quindi un test di identità è l'approccio giusto, ma è anche limitante. Gli oggetti di tipo bool sono anatre piuttosto strane in Python comunque, un'aggiunta relativamente recente al linguaggio. In ogni caso, opterei per il più semplice: 'sum (1 per b in boollist se b è True)' –

73

list ha un metodo count:

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

Non riesco a contare i valori False se c'è anche il valore 0 – Kostanos

+2

Non puoi usare 'sum' del altra risposta se si hanno altri valori "veri" oltre a 1 o True. Inoltre, la domanda non menzionava nient'altro che "True" o "False". –

2

È più sicuro eseguire prima il numero bool. Questo è fatto facilmente:

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

Poi si prenderà tutto ciò che Python considera True o False nel secchio appropriata:

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

Se si preferisce, è possibile utilizzare una comprensione:

>>> 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 per completezza (sum di solito è preferibile), volevo menzionare che possiamo anche usare filter per ottenere i valori di verità.Nel solito caso, filter accetta una funzione come primo argomento, ma se la passi None, filtrerà per tutti i valori "veri". Questa caratteristica è un po 'sorprendente, ma è ben documentato e funziona sia in Python 2 e 3.

La differenza tra le versioni, è che in Python 2 filter restituisce una lista, in modo che possiamo utilizzare len:

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

Ma in Python 3, filter restituisce un iteratore, quindi non possiamo usare len, e se vogliamo evitare di usare sum (per qualsiasi motivo) dobbiamo ricorrere alla conversione dell'iteratore in una lista (il che rende molto meno pretty):

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