2010-09-24 17 views
55

In alcuni dei miei codici metto una serie di oggetti in una lista e costruisco una lista aggiuntiva dei loro attributi, che è una stringa. Ho bisogno di determinare se tutti gli elementi in questa seconda lista hanno lo stesso identico valore, senza sapere in anticipo quale valore è, e restituire un bool in modo che io possa fare cose diverse nel mio codice a seconda del risultato.Python: determina se tutti gli elementi di una lista sono la stessa voce

Non riesco a conoscere i nomi delle proprietà in anticipo, è per questo che sto cercando di fare qualcosa di più generico possibile.

Per rendere il chiaro esempio, una funzione ideale, chiamata "all_same" dovrebbe funzionare in questo modo:

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

stavo pensando di fare un elenco di elementi unici e quindi verificare se la sua lunghezza è di 1, ma Non sono sicuro che sia la soluzione più elegante là fuori.

+0

appena realizzato che ho chiesto la stessa domanda qui: http://stackoverflow.com/questions/3844801/check-if-all-elements-in-a-list-are-identical. Come collego queste due domande? – max

+0

Heh, prima domanda ho visto dove una domanda precedente è il duplicato. Il tempo a volte funziona al contrario. – wheaties

risposta

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

Esempio:

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

Molto bello, userò questo, grazie! – Einar

+22

'len (set (items)) == 1' è più veloce. – JulienD

+1

@muraveill Ciò dipenderebbe molto dall'input. – FogleBird

41

Si potrebbe barare e utilizzare set:

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

o si potrebbe usare:

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

o se hai a che fare con un iterabile invece di una lista:

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

Il set avrebbe solo un elemento, l'elenco avrebbe N. – FogleBird

+1

È possibile utilizzare l'espressione del generatore nel 2 ° codice. 'all (x == items [0] per x negli elementi)'. – kennytm

+10

len (set (items)) == 1 sicuramente più idiomatico. –

9

Originariamente ho interpretato di essere in prova di identità ("la stessa voce"), ma siete veramente testando uguaglianza ("stesso valore"). (. Se tu fossi testando identità, utilizzare è invece di ==)

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) 

I lavori di cui sopra su ogni iterabile, non solo liste, altrimenti si potrebbe usare:

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

(Ma, IMHO, si potrebbe anche utilizzare la versione-it generale funziona perfettamente bene su liste)

+0

+1 Dovrò ricordare quella ricetta. – aaronasterling

+0

@katrielalex: Quindi devi provare/ad eccezione di StopIteration; a quel punto, è il comportamento equivalente e la stessa lunghezza. –

+1

Preferisco 'try: first = next (it) tranne StopIteration: return True' - Penso che il flusso sia più chiaro - ma la stessa differenza, davvero. – katrielalex

4

Questo funziona sia per le sequenze e iterabili:.

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

Ah, immaginavo che avresti controllato "prima è Nessuno" invece di lasciare che questo fall-through. Dà il risultato giusto, ma preferisco trattare questo errore/"circostanza eccezionale" invece di dipendere dal codice successivo per fare silenziosamente la cosa giusta. –

+0

So che sono molto spitico in questa opinione, ma non mi piace il fatto che una singola linea si trasforma in quattro perché devo prendere un'eccezione (io parlo in generale, tu hai usato una risposta per/break in). Sì, ho saputo di EAFP, ma ancora, se posso evitarlo ... Grazie per il +1, però :-) – tokland

0

È probabile che sia più veloce se si conoscono i valori in un elenco.

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

modo migliore per farlo è quello di utilizzare Python sets.You necessario definire all_same in questo modo:

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

prova:

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

Ho creato questo frammento di codice per quello stesso problema dopo averlo pensato. Non sono esattamente sicuro se funziona comunque per ogni scenario.

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

Ho paura che questo non funzioni affatto. Per esempio.'test_list = [1, 1]' e 'all_same (test_list)' restituisce 'False' perché' test_list [0] = 1' e 'len (test_list) = 2' quindi il risultato è solo' 1 * 2 = 2' . Quindi esegui il test '2 == test_list', che non è True. –

Problemi correlati