447 votes

Vérifiez si tous les éléments d’une liste sont identiques

J'ai besoin de la fonction suivante:

Entrée: un list

Sortie:

  • True si tous les éléments dans la liste d'entrée évaluer comme égaux les uns aux autres en utilisant la norme opérateur d'égalité;
  • False sinon.

Performance: bien sûr, je préfère ne pas entraîner de surcharge inutile.

Je pense qu'il serait préférable de:

  • parcourir la liste
  • comparer les éléments adjacents
  • et AND les valeurs Booléennes

Mais je ne suis pas sûr de ce qui est le plus Pythonic façon de le faire.


EDIT:

Merci pour toutes les réponses grands. J'ai noté plusieurs, et c'était vraiment dur de choisir entre @KennyTM et @Ivo van der Wijk solutions.

L'absence de court-circuit fonctionnalité ne blesse sur une longue entrée (plus de ~50 éléments) qui ont des éléments dès le début. Si cela se produit assez souvent (à quelle fréquence dépend de combien de temps les listes pourraient l'être), le court-circuit est nécessaire. Le meilleur court-circuit de l'algorithme semble être @KennyTM checkEqual1. Il est utile, cependant, un coût important pour ceci:

  • jusqu'à 20x performances presque identiques listes
  • jusqu'à 2,5 x de performance sur des listes

Si le long entrées avec le début de l'inégalité des éléments ne se produisent pas (ou produire suffisamment rarement), de court-circuit n'est pas nécessaire. Puis, de loin la plus rapide est @Ivo van der Wijk solution.

479voto

KennyTM Points 232647

Méthode générale:

   def checkEqual1(iterator):
      try:
         iterator = iter(iterator)
         first = next(iterator)
         return all(first == rest for rest in iterator)
      except StopIteration:
         return True

One-liner:

    def checkEqual2(iterator):
       return len(set(iterator)) <= 1

Aussi one-liner:

    def checkEqual3(lst):
       return lst[1:] == lst[:-1]

La différence entre les 3 versions sont les suivantes:

  1. En checkEqual2 le contenu doit être hashable.
  2. checkEqual1 et checkEqual2 pouvez utiliser n'importe quel itérateurs, mais checkEqual3 doit prendre une séquence d'entrée, généralement en béton conteneurs comme une liste ou un tuple.
  3. checkEqual1 s'arrête dès qu'un écart est constaté.
  4. Depuis checkEqual1 contient plus de code Python, il est moins efficace, alors que de nombreux éléments sont égaux dans le début.
  5. Depuis checkEqual2 et checkEqual3 toujours effectuer O(N) opérations de copie, ils vont prendre plus de temps si la plupart de votre entrée sera de retour Faux.
  6. checkEqual2 et checkEqual3 ne peut pas être facilement changé pour adopter de comparer a is b au lieu de a == b.

timeit le résultat, pour Python 2.7 et (que s1, s4, s7, s9 doit retourner True)

s1 = [1] * 5000
s2 = [1] * 4999 + [2]
s3 = [2] + [1]*4999
s4 = [set([9])] * 5000
s5 = [set([9])] * 4999 + [set([10])]
s6 = [set([10])] + [set([9])] * 4999
s7 = [1,1]
s8 = [1,2]
s9 = []

nous obtenons

     checkEqual1  checkEqual2   checkEqual3 checkEqualIvo checkEqual6502

s1 1.19     msec  348    usec  183     usec   51.6   usec   121     usec
s2 1.17     msec  376    usec  185     usec   50.9   usec   118     usec
s3     4.17 usec  348    usec  120     usec  264     usec    61.3   usec

s4 1.73     msec               182     usec   50.5   usec   121     usec
s5 1.71     msec               181     usec   50.6   usec   125     usec
s6     4.29 usec               122     usec  423     usec    61.1   usec

s7     3.1  usec    1.4  usec    1.24  usec    0.932 usec     1.92  usec
s8     4.07 usec    1.54 usec    1.28  usec    0.997 usec     1.79  usec
s9     5.91 usec    1.25 usec    0.749 usec    0.407 usec     0.386 usec

Note:

# http://stackoverflow.com/q/3844948/
def checkEqualIvo(lst):
    return not lst or lst.count(lst[0]) == len(lst)

# http://stackoverflow.com/q/3844931/
def checkEqual6502(lst):
    return not lst or [lst[0]]*len(lst) == lst

328voto

Ivo van der Wijk Points 7239

Une solution plus rapide que d’utiliser set() qui fonctionne sur les séquences (pas Iterable) doit compter simplement le premier élément. Cela suppose que la liste n’est pas vide (mais c’est trivial de vérifier et décidez vous-même ce que le résultat devrait être sur une liste vide)

quelques repères simples :

192voto

ninjagecko Points 25709

Le moyen plus simple et la plus élégant est comme suit :

(Oui, cela fonctionne même avec la liste nulle ! C’est parce que c’est l’un des rares cas où python est a une sémantique paresseuse.)

Au sujet de la performance, cela échouera dans les plus brefs délais, est asymptotiquement optimale.

Modifier par user2324363 : changé = à ==

35voto

codaddict Points 154968

Vous pouvez convertir la liste en un ensemble. Un ensemble ne peut pas avoir de doublons. Ainsi, si tous les éléments dans la liste originale sont identiques, le jeu aura qu’un seul élément.

11voto

6502 Points 42700

Ceci est une autre option, plus rapide que len(set(x))==1 pour les longues listes (utilise un court-circuit)

 def constantList(x):
    return x and [x[0]]*len(x) == 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