web-dev-qa-db-fra.com

Compter le nombre de vrais booléens dans une liste Python

J'ai une liste de booléens:

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

et je cherche un moyen de compter le nombre de True dans la liste (dans l'exemple ci-dessus, je veux que le retour soit 3.) J'ai trouvé des exemples de recherche du nombre d'occurrences d'éléments spécifiques, mais existe-t-il un moyen plus efficace de le faire puisque je travaille avec des booléens? Je pense à quelque chose d'analogue à all ou any.

100
acs

True est égal à 1.

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

list a une méthode count:

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

C’est en fait plus efficace que sum, tout en étant plus explicite sur l’intention, il n’ya donc aucune raison d’utiliser 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)
88
Mark Tolonen

Si vous êtes uniquement préoccupé par la constante True, une simple sum convient. Cependant, gardez à l'esprit qu'en Python, les autres valeurs sont également évaluées par True. Une solution plus robuste consisterait à utiliser la variable bool intégrée:

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

MISE À JOUR: Voici une autre solution tout aussi robuste qui présente l’avantage d’être plus transparente:

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

P.S. Jeu-questionnaire en python: True pourrait être vrai sans être 1. Attention: n'essayez pas cela au travail!

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

Beaucoup plus diabolique:

True = False
38
Ned Deily

Vous pouvez utiliser sum():

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

Juste pour être complet (sum est généralement préférable), je voulais mentionner que nous pouvons également utiliser filter pour obtenir les valeurs de vérité. Dans le cas habituel, filter accepte une fonction en tant que premier argument, mais si vous le transmettez à None, il filtrera toutes les valeurs "vérité". Cette fonctionnalité est quelque peu surprenante, mais elle est bien documentée et fonctionne à la fois en Python 2 et 3.

La différence entre les versions est que, dans Python 2, filter renvoie une liste, nous pouvons donc utiliser len:

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

Mais dans Python 3, filter renvoie un itérateur. Nous ne pouvons donc pas utiliser len. Si nous voulons éviter d'utiliser sum (quelle que soit la raison), nous devons convertir l'itérateur en liste (ce qui le rend beaucoup moins joli). :

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

Il est plus sûr de parcourir d'abord bool. C'est facile à faire:

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

Ensuite, vous allez attraper tout ce que Python considère comme étant vrai ou faux dans le compartiment approprié:

>>> 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 vous préférez, vous pouvez utiliser une compréhension:

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

Je préfère len([b for b in boollist if b is True]) (ou l'équivalent générateur-expression), car c'est assez explicite. Moins "magique" que la réponse proposée par Ignacio Vazquez-Abrams.

Vous pouvez aussi faire cela, ce qui suppose toujours que bool est convertible en int, mais ne fait aucune hypothèse concernant la valeur de True: ntrue = sum(boollist) / int(True)

1
kampu

Après avoir lu toutes les réponses et commentaires sur cette question, j'ai pensé faire une petite expérience.

J'ai généré 50 000 booléens aléatoires et appelé sum et count sur eux.

Voici mes résultats:

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

Juste pour être sûr, je l'ai répété plusieurs fois:

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

Et comme vous pouvez le constater, count est 3 fois plus rapide que sum. Je suggère donc d'utiliser count comme je l'ai fait dans count_it.

Version Python: 3.6.7
Cœurs de la CPU: 4
Taille de la RAM: 16 Go
OS: Ubuntu 18.04.1 LTS

0
GMishx