comprobar si todos los elementos de una lista son idénticos
Necesito la siguiente función:
Entrada : a list
Salida:
-
True
si todos los elementos de la lista de entrada se evalúan como iguales entre sí utilizando el operador de igualdad estándar; -
False
de lo contrario.
Rendimiento : por supuesto, prefiero no incurrir en gastos generales innecesarios.
Creo que sería mejor:
- iterar a través de la lista
- comparar adyacente elementos
- y
AND
todos los valores booleanos resultantes
Pero no estoy seguro de cuál es la forma más pitónica de hacer eso.
EDITAR :
Gracias por todas las grandes respuestas. Yo nominal de hasta varios, y fue muy difícil elegir entre @KennyTM y @Ivo van der Wijk soluciones.
La falta de función de cortocircuito solo duele en una entrada larga (más de ~50 elementos) que tienen elementos desiguales al principio. Si esto ocurre con la frecuencia suficiente (con qué frecuencia depende de la longitud de las listas), se requiere el cortocircuito. El mejor algoritmo de cortocircuito parece ser @KennyTM checkEqual1
. Paga, sin embargo, un costo significativo por esto:
- hasta 20 veces en listas de rendimiento casi idénticas
- hasta 2,5 veces en rendimiento en listas cortas
Si las entradas largas con elementos desiguales tempranos no ocurren (o ocurren suficientemente raramente), no se requiere cortocircuito. Entonces, con mucho, el más rápido es @Ivo van der Wijk solución.
21 answers
Método general:
def checkEqual1(iterator):
iterator = iter(iterator)
try:
first = next(iterator)
except StopIteration:
return True
return all(first == rest for rest in iterator)
Una sola línea:
def checkEqual2(iterator):
return len(set(iterator)) <= 1
También de una sola línea:
def checkEqual3(lst):
return lst[1:] == lst[:-1]
La diferencia entre las 3 versiones es que:
-
{[28] {} En[6]} el contenido debe ser hashable.
-
checkEqual1
ycheckEqual2
pueden usar cualquier iterador, perocheckEqual3
debe tomar una entrada de secuencia, típicamente contenedores de concreto como una lista o tupla. -
checkEqual1
se detiene tan pronto como se encuentra una diferencia. - Dado que
checkEqual1
contiene más código Python, es menos eficiente cuando muchos de los elementos son iguales al principio. - Dado que
checkEqual2
ycheckEqual3
siempre realizan operaciones de copia O(N), tardarán más si la mayor parte de su entrada devuelve False. - Para
checkEqual2
ycheckEqual3
es más difícil adaptar la comparación dea == b
aa is b
.
timeit
resultado, para Python 2.7 y (solo s1, s4, s7, s9 debe devolver 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 = []
Obtenemos
| 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 |
Nota:
# 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-11 21:38:35
Una solución más rápida que usar set() que funciona en secuencias (no iterables) es simplemente contar el primer elemento. Esto asume que la lista no está vacía (pero eso es trivial de verificar y decidir por ti mismo cuál debe ser el resultado en una lista vacía)
x.count(x[0]) == len(x)
Algunos puntos de referencia simples:
>>> timeit.timeit('len(set(s1))<=1', 's1=[1]*5000', number=10000)
1.4383411407470703
>>> timeit.timeit('len(set(s1))<=1', 's1=[1]*4999+[2]', number=10000)
1.4765670299530029
>>> timeit.timeit('s1.count(s1[0])==len(s1)', 's1=[1]*5000', number=10000)
0.26274609565734863
>>> timeit.timeit('s1.count(s1[0])==len(s1)', 's1=[1]*4999+[2]', number=10000)
0.25654196739196777
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-02 08:25:21
La forma más simple y elegante es la siguiente:
all(x==myList[0] for x in myList)
(¡Sí, esto incluso funciona con la lista nula! Esto se debe a que este es uno de los pocos casos en los que python tiene semántica perezosa.)
En cuanto al rendimiento, esto fallará lo antes posible, por lo que es asintóticamente óptimo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-24 20:49:58
Un trabajo de comparación de conjuntos:
len(set(the_list)) == 1
Usando set
elimina todos los elementos duplicados.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-16 01:06:34
Puede convertir la lista a un conjunto. Un conjunto no puede tener duplicados. Así que si todos los elementos de la lista original son idénticos, el conjunto tendrá solo un elemento.
if len(sets.Set(input_list)) == 1
// input_list has all identical elements.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-02 07:51:52
Por si sirve de algo, esto surgió recientemente en la lista de correo de python-ideas. Resulta que hay una receta de itertools para hacer esto ya:1
def all_equal(iterable):
"Returns True if all the elements are equal to each other"
g = groupby(iterable)
return next(g, True) and not next(g, False)
Supuestamente funciona muy bien y tiene algunas propiedades agradables.
- Cortocircuitos: Dejará de consumir elementos del iterable tan pronto como encuentre el primer elemento no igual.
- No requiere que los elementos sean hashables.
- Es perezoso y solo requiere O (1) memoria adicional para hacer la comprobación.
1En otras palabras, no puedo tomar el crédito para llegar a la solución nor ni puedo tomar el crédito para incluso encontrar.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-06 23:16:59
Esta es otra opción, más rápida que len(set(x))==1
para listas largas (usa cortocircuito)
def constantList(x):
return x and [x[0]]*len(x) == x
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-02 08:22:50
Esta es una forma sencilla de hacerlo:
result = mylist and all(mylist[0] == elem for elem in mylist)
Esto es un poco más complicado, incurre en sobrecarga de llamadas a funciones, pero la semántica está más claramente explicada:
def all_identical(seq):
if not seq:
# empty list is False.
return False
first = seq[0]
return all(first == elem for elem in seq)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-02 08:11:43
Duda que este es el "más pitónico", pero algo así como:
>>> falseList = [1,2,3,4]
>>> trueList = [1, 1, 1]
>>>
>>> def testList(list):
... for item in list[1:]:
... if item != list[0]:
... return False
... return True
...
>>> testList(falseList)
False
>>> testList(trueList)
True
Haría el truco.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-02 07:39:45
Si usted está interesado en algo un poco más legible (pero por supuesto no tan eficiente,) usted podría intentar:
def compare_lists(list1, list2):
if len(list1) != len(list2): # Weed out unequal length lists.
return False
for item in list1:
if item not in list2:
return False
return True
a_list_1 = ['apple', 'orange', 'grape', 'pear']
a_list_2 = ['pear', 'orange', 'grape', 'apple']
b_list_1 = ['apple', 'orange', 'grape', 'pear']
b_list_2 = ['apple', 'orange', 'banana', 'pear']
c_list_1 = ['apple', 'orange', 'grape']
c_list_2 = ['grape', 'orange']
print compare_lists(a_list_1, a_list_2) # Returns True
print compare_lists(b_list_1, b_list_2) # Returns False
print compare_lists(c_list_1, c_list_2) # Returns False
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-04 20:22:01
Yo haría:
not any((x[i] != x[i+1] for i in range(0, len(x)-1)))
Como any
deja de buscar el iterable tan pronto como encuentra una condición True
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-13 18:19:47
Con respecto a usar reduce()
con lambda
. Aquí hay un código de trabajo que personalmente creo que es mucho más agradable que algunas de las otras respuestas.
reduce(lambda x, y: (x[1]==y, y), [2, 2, 2], (True, 2))
Devuelve una truple donde el primer valor es el booleano si todos los elementos son iguales o no.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-21 08:51:48
Compruebe si todos los elementos son iguales al primero.
np.allclose(array, array[0])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-26 14:59:45
Convierta la lista en el conjunto y luego encuentre el número de elementos en el conjunto. Si el resultado es 1, tiene elementos idénticos y si no, entonces los elementos de la lista no son idénticos.
list1 = [1,1,1]
len(set(list1))
>1
list1 = [1,2,3]
len(set(list1)
>3
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-26 06:02:29
Aquí hay dos formas simples de hacer esto
Usando set ()
Al convertir la lista a un conjunto, se eliminan los elementos duplicados. Así que si la longitud del conjunto convertido es 1, entonces esto implica que todos los elementos son los mismos.
len(set(input_list))==1
He aquí un ejemplo
>>> a = ['not', 'the', 'same']
>>> b = ['same', 'same', 'same']
>>> len(set(a))==1 # == 3
False
>>> len(set(b))==1 # == 1
True
Usando all ()
Esto comparará (equivalencia) el primer elemento de la lista de entrada con todos los demás elementos de la lista. Si todos son equivalentes True será devuelto, de lo contrario False será devuelto.
all(element==input_list[0] for element in input_list)
He aquí un ejemplo
>>> a = [1, 2, 3, 4, 5]
>>> b = [1, 1, 1, 1, 1]
>>> all(number==a[0] for number in a)
False
>>> all(number==b[0] for number in b)
True
P. S Si usted está comprobando para ver si la lista entera es equivalente a un cierto valor, usted puede suibstitue el valor adentro para input_list [0].
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-24 18:47:42
>>> a = [1, 2, 3, 4, 5, 6]
>>> z = [(a[x], a[x+1]) for x in range(0, len(a)-1)]
>>> z
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
# Replacing it with the test
>>> z = [(a[x] == a[x+1]) for x in range(0, len(a)-1)]
>>> z
[False, False, False, False, False]
>>> if False in z : Print "All elements are not equal"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-02 07:45:27
def allTheSame(i):
j = itertools.groupby(i)
for k in j: break
for k in j: return False
return True
Funciona en Python 2.4, que no tiene "todo".
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-10 06:28:29
Puede usar map y lambda
lst = [1,1,1,1,1,1,1,1,1]
print all(map(lambda x: x == lst[0], lst[1:]))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-13 05:22:56
Puedes hacer:
reduce(and_, (x==yourList[0] for x in yourList), True)
Es bastante molesto que python te haga importar operadores como operator.and_
. A partir de python3, también necesitarás importar functools.reduce
.
(No debe usar este método porque no se romperá si encuentra valores no iguales, sino que continuará examinando toda la lista. Solo se incluye aquí como una respuesta para completar.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-24 17:40:02
lambda lst: reduce(lambda a,b:(b,b==a[0] and a[1]), lst, (lst[0], True))[1]
El próximo cortocircuito cortocircuito:
all(itertools.imap(lambda i:yourlist[i]==yourlist[i+1], xrange(len(yourlist)-1)))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-27 09:46:25
Cambie la lista a un conjunto. Entonces, si el tamaño del conjunto es solo 1, deben haber sido el mismo.
if len(set(my_list)) == 1:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-15 08:34:42