2010-09-24 16 views
55

En algunos de mis códigos coloco una serie de objetos en una lista y construyo una lista adicional de sus atributos, que es una cadena. Necesito determinar si todos los elementos en esta segunda lista tienen exactamente el mismo valor, sin saber de antemano qué valor es, y devolver un bool para poder hacer cosas diferentes en mi código dependiendo del resultado.Python: determine si todos los elementos de una lista son el mismo artículo

No puedo saber los nombres de las propiedades de antemano, es por eso que estoy tratando de hacer algo tan genérico como sea posible.

Para hacer el claro ejemplo, una función de ideales, llamado "all_same" sería el siguiente:

>>> property_list = ["one", "one", "one"] 
>>> all_same(property_list) 
True 
>>> property_list = ["one", "one", "two"] 
>>> all_same(property_list) 
False 

Estaba pensando en hacer una lista de elementos únicos y luego comprobar si su longitud es de 1, pero No estoy seguro de si es la solución más elegante que existe.

+0

di cuenta de que me hice la misma pregunta aquí: http://stackoverflow.com/questions/3844801/check-if-all-elements-in-a-list-are-identical. ¿Cómo puedo vincular estas dos preguntas? – max

+0

Heh, primera pregunta que he visto donde una pregunta anterior es el duplicado. El tiempo a veces funciona a la inversa. – wheaties

Respuesta

102
def all_same(items): 
    return all(x == items[0] for x in items) 

Ejemplo:

>>> def all_same(items): 
...  return all(x == items[0] for x in items) 
... 
>>> property_list = ["one", "one", "one"] 
>>> all_same(property_list) 
True 
>>> property_list = ["one", "one", "two"] 
>>> all_same(property_list) 
False 
>>> all_same([]) 
True 
+0

Muy bien, usaré este, ¡gracias! – Einar

+22

'len (set (items)) == 1' es más rápido. – JulienD

+1

@muraveill Eso dependería en gran medida de la entrada. – FogleBird

41

Se puede engañar y utilizar set:

def all_same(items): 
    return len(set(items)) == 1 #== len(items) 

o puede utilizar:

def all_same(items): 
    return all(map(lambda x: x == items[0], items)) 

o si está tratando con un iterable en lugar de una lista:

def all_same(iterable): 
    it_copy = tee(iterable, 1) 
    return len(set(it_copy)) == 1 
+0

El conjunto tendría solo un elemento, la lista tendría N. – FogleBird

+1

Puede usar la expresión del generador en el segundo código. 'todo (x == elementos [0] para x en elementos)'. – kennytm

+10

len (set (items)) == 1 definitivamente más idiomático. –

9

originalmente interpreté que estar poniendo a prueba la identidad ("el mismo punto"), pero en realidad está probando la igualdad ("mismo valor"). (. Si estuviera haciendo la prueba de identidad, utilice es en lugar de ==)

def all_same(items): 
    it = iter(items) 
    for first in it: 
    break 
    else: 
    return True # empty case, note all([]) == True 
    return all(x == first for x in it) 

Los trabajos anteriores en cualquier iterable, no sólo enumera, de lo contrario podría usar:

def all_same(L): 
    return all(x == L[0] for x in L) 

(Pero, en mi humilde opinión, que también podría utilizar la versión de que en general funciona perfectamente bien en las listas)

+0

+1 Tendré que recordar esa receta. – aaronasterling

+0

@katrielalex: Entonces tienes que probar/a excepción de StopIteration; en ese punto, es un comportamiento equivalente y la misma longitud. –

+1

Prefiero 'try: first = next (it) excepto StopIteration: return True' - Creo que el flujo es más claro - pero la misma diferencia, en realidad. – katrielalex

4

Esto funciona tanto para las secuencias y iterables:.

def all_same(items): 
    it = iter(items) 
    first = next(it, None) 
    return all(x == first for x in it) 
+1

Ah, me estaba imaginando que verificaría "primero es Ninguno" en lugar de dejar que esto suceda. Da el resultado correcto, pero prefiero tratar este un error/"circunstancia excepcional" en lugar de depender del código posterior para hacer lo correcto en silencio. –

+0

Sé que soy muy poco entusiasta en esta opinión, pero no me gusta que una línea única se convierta en cuatro porque tengo que atrapar una excepción (hablo en general, usted usó un for/break en su respuesta). Sí, sabía sobre EAFP, pero aún así, si puedo evitarlo ... Gracias por el +1, aunque :-) – tokland

0

Es probable que sea más rápido si sabe que los valores están en una lista.

def all_same(values): 
    return values.count(values[0]) == len(values) 
5

mejor manera de hacer esto es utilizar Python sets.You necesita definir all_same así:

def all_same(items): 
    return len(set(items)) == 1 

prueba:

>>> def all_same(items): 
...  return len(set(items)) == 1 
... 
>>> 
>>> property_list = ["one", "one", "one"] 
>>> all_same(property_list) 
True 
>>> property_list = ["one", "one", "two"] 
>>> all_same(property_list) 
False 
>>> 
-1

creé este fragmento de código para el mismo problema después de pensarlo. Sin embargo, no estoy exactamente seguro si funciona para todos los escenarios.

def all_same(list): 
    list[0]*len(list) == list 
+0

Me temo que esto no funciona en absoluto. P.ej.'test_list = [1, 1]' y 'all_same (test_list)' devuelve 'False' porque' test_list [0] = 1' y 'len (test_list) = 2', por lo que los resultados son simplemente' 1 * 2 = 2' . Luego, prueba '2 == test_list', que no es True. –

Cuestiones relacionadas