40 votes

Python: comment savoir si ma liste contient tous les 1?

Je cherche un meilleur moyen, peut-être utiliser des listes compréhensives?

 >>> x = [1, 1, 1, 1, 1, 1]
>>> x
[1, 1, 1, 1, 1, 1]
>>> for i in x:
...   if i!=1:
...     print "fail"
... 
>>> 
>>> x = [1, 1, 1, 1, 1, 0]
>>> for i in x:
...   if i!=1:
...     print "fail"
... 
fail
>>> 
 

78voto

Oleh Prypin Points 9086
>>> x = [1, 1, 1, 1, 1, 1]
>>> all(el==1 for el in x)
True

Cette fonction utilise la fonction all avec un générateur d'expression.


Si vous avez toujours uniquement de zéros et de uns dans la liste (ou si vous voulez juste vérifier si la liste n'ont pas de zéros), alors il suffit d'utiliser all sans ajouter astuces:

>>> x = [1, 0, 1, 1, 1, 0]
>>> all(x)
False

Test de quelques solutions:
Les chiffres sont ce que de temps en millisecondes qu'il a fallu pour exécuter la solution une fois (moyenne de 1000 timeit pistes)

Python 3.2.3

              all(el==1 for el in x): 0.0003 0.0008 0.7903 0.0804 0.0005 0.0006
                       x==[1]*len(x): 0.0002 0.0003 0.0714 0.0086 0.0045 0.0554
         not([1 for y in x if y!=1]): 0.0003 0.0005 0.4142 0.1117 0.1100 1.1630
                set(x).issubset({1}): 0.0003 0.0005 0.2039 0.0409 0.0476 0.5310
y = set(x); len(y)==1 and y.pop()==1:   WA   0.0006 0.2043 0.0517 0.0409 0.4170
                   max(x)==1==min(x):   RE   0.0006 0.4574 0.0460 0.0917 0.5466
                 tuple(set(x))==(1,):   WA   0.0006 0.2046 0.0410 0.0408 0.4238
not(bool(filter(lambda y: y!=1, x))):   WA     WA     WA   0.0004 0.0004 0.0004
                              all(x): 0.0001 0.0001 0.0839   WA   0.0001   WA  

Python 2.7.3

              all(el==1 for el in x): 0.0003 0.0008 0.7175 0.0751 0.0006 0.0006
                       x==[1]*len(x): 0.0002 0.0003 0.0741 0.0110 0.0094 0.1015
         not([1 for y in x if y!=1]): 0.0001 0.0003 0.3908 0.0948 0.0954 0.9840
                set(x).issubset({1}): 0.0003 0.0005 0.2084 0.0422 0.0420 0.4198
y = set(x); len(y)==1 and y.pop()==1:   WA   0.0006 0.2083 0.0421 0.0418 0.4178
                   max(x)==1==min(x):   RE   0.0006 0.4568 0.0442 0.0866 0.4937
                 tuple(set(x))==(1,):   WA   0.0006 0.2086 0.0424 0.0421 0.4202
not(bool(filter(lambda y: y!=1, x))): 0.0004 0.0011 0.9809 0.1936 0.1925 2.0007
                              all(x): 0.0001 0.0001 0.0811   WA   0.0001   WA  

[PyPy 1.9.0] Python 2.7.2

              all(el==1 for el in x): 0.0013 0.0093 0.4148 0.0508 0.0036 0.0038
                       x==[1]*len(x): 0.0006 0.0009 0.4557 0.0575 0.0177 0.1368
         not([1 for y in x if y!=1]): 0.0009 0.0015 175.10 7.0742 6.4390 714.15 # No, this wasn't run 1000 times. Had to time it separately.
                set(x).issubset({1}): 0.0010 0.0020 0.0657 0.0138 0.0139 0.1303
y = set(x); len(y)==1 and y.pop()==1:   WA   0.0011 0.0651 0.0137 0.0137 0.1296
                   max(x)==1==min(x):   RE   0.0011 0.5892 0.0615 0.1171 0.5994
                 tuple(set(x))==(1,):   WA   0.0014 0.0656 0.0163 0.0142 0.1302
not(bool(filter(lambda y: y!=1, x))): 0.0030 0.0081 0.2171 0.0689 0.0680 0.7599
                              all(x): 0.0011 0.0044 0.0230   WA   0.0013   WA  

Les tests suivants ont été utilisés:

[] # True
[1]*6 # True
[1]*10000 # True
[1]*1000+[2]*1000 # False
[0]*1000+[1]*1000 # False
[random.randint(1, 2) for _ in range(20000)] # False

WA - dire que la solution a donné une mauvaise réponse; RE représente erreur d'exécution.


Donc mon verdict est, Winston Ewerts' x==[1]*len(x) solution est la plus rapide dans la plupart des cas. Si vous avez rarement des listes de tous ceux (les données sont aléatoires, etc.) ou vous ne souhaitez pas utiliser plus de RAM, ma solution fonctionne mieux. Si les listes sont de petite taille, la différence est négligeable.

42voto

Winston Ewert Points 17746

Encore plus de méthodes possibles:

 x == [1] * len(x)

list(set(x)) == [1]

tuple(set(x)) == (1,)
 

Quelques résultats de chronométrage:

 all(el==1 for el in x)                   [1.184262990951538, 1.1856739521026611, 1.1883699893951416]
y = set(x);len(y) == 1 and y.pop() == 1  [0.6140780448913574, 0.6152529716491699, 0.6156158447265625]
set(x) == set([1])                       [0.8093318939208984, 0.8106880187988281, 0.809283971786499]
not(bool(filter(lambda y: y!=1, x)))     [1.615243911743164, 1.621769905090332, 1.6134231090545654]
not any(i!=1 for i in x)                 [1.1321749687194824, 1.1325697898864746, 1.132157802581787]
x == [1]*len(x)                          [0.3790302276611328, 0.3765430450439453, 0.3812289237976074]
list(set(x)) == [1]                      [0.9047720432281494, 0.9006211757659912, 0.9024860858917236]
tuple(set(x)) == (1,)                    [0.6586658954620361, 0.6594271659851074, 0.6585478782653809]
 

Et sur PyPy parce que: pourquoi pas?

 all(el==1 for el in x)                   [0.40866899490356445, 0.5661730766296387, 0.45672082901000977]
y = set(x);len(y) == 1 and y.pop() == 1  [0.6929471492767334, 0.6925959587097168, 0.6805419921875]
set(x) == set([1])                       [0.956063985824585, 0.9526000022888184, 0.955935001373291]
not(bool(filter(lambda y: y!=1, x)))     [0.21160888671875, 0.1965351104736328, 0.19921493530273438]
not any(i!=1 for i in x)                 [0.44970107078552246, 0.509315013885498, 0.4380669593811035]
x == [1]*len(x)                          [0.5422029495239258, 0.5407819747924805, 0.5440030097961426]
list(set(x)) == [1]                      [1.0170629024505615, 0.9520189762115479, 0.940842866897583]
tuple(set(x)) == (1,)                    [0.9174900054931641, 0.9112720489501953, 0.9102160930633545]
 

16voto

sampson-chen Points 13413

En plus de l' all() de réponses déjà fournies, vous pouvez aussi le faire avec set():

>>> x = [1, 1, 1, 1, 1, 1]
>>> y = set(x)
>>> len(y) == 1 and y.pop() == 1
True

>>> a = [1, 1, 1, 1, 0]
>>> b = set(a)
>>> len(b) == 1 and b.pop() == 1
False

Mise en garde; (et Facteur de Rachat):

  • Comme certains l'ont souligné, c'est moins lisible; cependant...
  • Je vais quitter cette place depuis:
    • Les résultats obtenus en @WinstonEwert la réponse de démontrer, cette solution peut faire mieux que l' all() solution proposée par @BlaXpirit
    • Je pense que la plupart des membres de StackOverflow préfèrent apprendre de nouvelles choses; les solutions de rechange contribuer à cette fin par l'invitation de la discussion, de l'enquête et de l'analyse.

10voto

jimhark Points 2697

@sampson-chen a eu une bonne idée qui pourrait utiliser un peu d'aide. Considérer jusqu'à droit de vote de sa réponse et de regarder cela comme un long commentaire. (Je ne sais pas comment faire le code de bonne apparence dans un commentaire). Voici mon réécrire:

>>> setone = set([1])
>>> x = [1, 1, 1, 1, 1, 1]
>>> set(x) == setone
True

Ce code n'est pas exactement conforme à l'original question, car elle renvoie False pour une liste vide qui pourrait être bon ou mauvais, mais n'a probablement pas d'importance.

Modifier

Basé sur les commentaires de la communauté (merci @Nabb), voici un deuxième réécriture:

>>> x = [1, 1, 1, 1, 1, 1]
>>> set(x).issubset({1})

Ce gère correctement le cas où x est une liste vide.

Je pense que c'est lisible. Et la variante de la partie est plus rapide qu'à l'écrit (presque deux fois plus vite). En fait, sur mon Python 2.7 système, c'est toujours plus rapide pour les listes jusqu'à 20 éléments et pour les listes qui sont toutes les 1 du. (Jusqu'à 3 fois plus rapide.)

Mise à jour: Vides de sens, de Vérité et de Réduction de la Liste Vide

@Peter Olson a écrit dans un commentaire:

Si la liste est vide, alors la proposition "chaque élément de la liste correspond à un" est vacuously vrai.

La poursuite de la discussion dans les commentaires de plomb jusqu'à @sampson-chen écrit:

J'ai senti qu'il devrait être vacuously false; peut-être quelqu'un dans ce post va éventuellement nous éclairer sur la sémantique. – sampson-chen

Voyons ce que Python pense:

>>> all([])
True

Eh bien que diriez-vous:

>>> any([])
False

Alors pourquoi est-ce que le droit? Si vous n'avez pas exécuté dans ce avant elle peut être source de confusion. Il y a une manière de penser qui peuvent vous aider à comprendre et à mémoriser.

Nous allons revenir un peu en arrière et de commencer avec:

>>> sum(mylist)

Python fonction intégrée sum des sommes des éléments d'un objet iterable de gauche à droite et renvoie le total. Penser de manière plus abstraite, sum réduit un objet iterable par l'application de l'opérateur d'addition.

>>> sum([])
0

La somme de rien du tout est de 0. C'est assez intuitif. Mais ce:

>>> product([])

Ok, il fait renvoie une erreur de nom, car product n'existe pas en tant que fonction intégrée. Mais que doit - il revenir? 0? Non, la valeur d'un vide produit est de 1. Plus mathématiquement cohérente (cliquez sur le lien pour une explication complète), parce que 1 est l' identité de l'élément de multiplication. (Rappelez - sum([]) a retourné 0, l'identité de l'élément de plus.)

La prise de cette compréhension du rôle spécial que l'identité de l'élément de pièces de théâtre, et de revenir à l'origine du problème:

all([])

Est équivalente à réduire la liste à l'aide de la Boolean and de l'opérateur. L'identité de l'élément de and est Vraie, alors le résultat pour la liste vide est - True.

any([])

L'identité de l'élément de or est False, la même que la valeur de cette expression.

2voto

ckb Points 441

Cela parcourt la liste et rassemble tous les termes qui ne sont pas 1. Si ces termes existent, alors bool renvoie True et la réponse est False.

 not(bool(filter(lambda y: y!=1, x)))
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X