2009-08-20 14 views
141

Testato su Python 2.6 interprete:Python: Aggiungi lista da impostare?

>>> a=set('abcde') 
>>> a 
set(['a', 'c', 'b', 'e', 'd']) 
>>> l=['f','g'] 
>>> l 
['f', 'g'] 
>>> a.add(l) 
Traceback (most recent call last): 
    File "<pyshell#35>", line 1, in <module> 
    a.add(l) 
TypeError: list objects are unhashable 

penso che non posso aggiungere l'elenco per il set, perché non c'è modo Python può dire se ho aggiunto la stessa lista due volte. C'è una soluzione?

MODIFICA: Voglio aggiungere la lista stessa, non i suoi elementi.

+2

Vuoi aggiungere l'elenco al set o le voci della lista? – pkit

+0

La lista stessa - Voglio avere una serie di liste. –

+0

Quindi utilizzare l'opzione tupla a cui ha risposto Otto. – pkit

risposta

131

Non è possibile aggiungere un elenco a un set perché gli elenchi sono modificabili, ovvero è possibile modificare il contenuto dell'elenco dopo averlo aggiunto al set.

È possibile tuttavia aggiungere tuple al set, perché non è possibile modificare il contenuto di una tupla:

>>> a.add(('f', 'g')) 
>>> print a 
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')]) 

Edit: qualche spiegazione: La documentazione definisce un set come una collezione non ordinata di distinti oggetti lavabili. Gli oggetti devono essere lavabili in modo che la ricerca, l'aggiunta e la rimozione di elementi possano essere eseguiti più rapidamente rispetto a ogni singolo elemento ogni volta che si eseguono queste operazioni. Gli algoritmi specifici utilizzati sono illustrati nello Wikipedia article. Gli algoritmi di assegnazione dei pitoni sono spiegati nella funzione effbot.org e nei pitoni __hash__ nello python reference.

Alcuni fatti:

  • Set elementi così come chiavi del dizionario devono essere hashable
  • Alcuni tipi di dati nel calcolo dell'hash:
    • list: utilizzare tuple invece
    • set: utilizzare frozenset invece
    • dict: non ha riscontro ufficiale, ma ci sono alcuni recipes
  • istanze degli oggetti vengono hashable di default con ogni istanza avere un hash univoco. Puoi sovrascrivere questo comportamento come spiegato nel riferimento a Python.
+4

E se si desidera aggiungere un set a un set, utilizzare frozenset. – FogleBird

+4

['collections.namedtuple'] (http://docs.python.org/library/collections.html#collections.namedtuple) potrebbe essere considerato controparte" ufficiale "del' dict'. – SilentGhost

+2

@FogleBird o l'operatore unione: | = – aehlke

332
>>> a = set('abcde') 
>>> l = ['f', 'g'] 
>>> a |= set(l) 
>>> a 
set(['a', 'c', 'b', 'e', 'd', 'g', 'f']) 

operatore Il sindacato è molto più veloce di aggiungere in ogni caso.

modifica: Se si desidera la lista stessa e non i suoi membri, è necessario utilizzare una tupla, sfortunatamente. Impostare i membri deve essere lavabile.

+20

'a.update (l)' ha lo stesso effetto. –

8

elenco oggetti sono inagibili. tuttavia potresti volerli trasformare in tuple.

3

Dovrai utilizzare le tuple, che sono lavabili (non puoi hash un oggetto mutabile come una lista).

>>> a = set("abcde") 
>>> a 
set(['a', 'c', 'b', 'e', 'd']) 
>>> t = ('f', 'g') 
>>> a.add(t) 
>>> a 
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')]) 
+0

Wow, abbiamo scritto quasi esattamente la stessa cosa allo stesso tempo. – hughdbrown

4

si desidera aggiungere una tupla, non una lista:

>>> a=set('abcde') 
>>> a 
set(['a', 'c', 'b', 'e', 'd']) 
>>> l=['f','g'] 
>>> l 
['f', 'g'] 
>>> t = tuple(l) 
>>> t 
('f', 'g') 
>>> a.add(t) 
>>> a 
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')]) 

Se si dispone di un elenco, è possibile convertire il tuple, come indicato sopra. Una tupla è immutabile, quindi può essere aggiunta al set.

+0

non hai bisogno di 'tupla (x per x in l)', puoi semplicemente fare: 'tuple (l)' – SilentGhost

+0

Ah, giusto. Ho una sintassi di comprensione delle liste bloccata tra le dita. – hughdbrown

4

Gli insiemi non possono avere elementi/membri mutabili (modificabili). Un elenco, essendo mutabile, non può essere un membro di un set.

Poiché i set sono mutabili, non è possibile avere un set di set! Puoi comunque avere un set di frozenset.

(Lo stesso tipo di "requisito mutevolezza" vale anche per i tasti di un dict.)

altre risposte hanno già dato il codice, spero che questo dà un po 'di comprensione. Spero che Alex Martelli risponda con ancora più dettagli.

2

Ho trovato che dovevo fare qualcosa di simile oggi. L'algoritmo sapeva quando stava creando una nuova lista che doveva essere aggiunta al set, ma non quando avrebbe finito di funzionare sulla lista.

In ogni caso, il comportamento che volevo era impostato per utilizzare id anziché hash. Come tale ho trovato mydict[id(mylist)] = mylist invece di myset.add(mylist) per offrire il comportamento che volevo.

13

Si prega di notare la funzione set.update(). La documentazione dice:

Aggiornare un set con l'unione di se stesso e di altri.

+5

Questo non risponde alla domanda (dal momento che l'OP vuole aggiungere la lista stessa al set) ma era la risposta di cui avevo bisogno quando Google mi ha portato qui :-) –

+1

Beh, sembra la risposta più pertinente al domanda per me ... per esempio, se b = set ([1]), b.update ([7,25]) darà b il seguente valore: set ([1, 25, 7]) ---> Non è quello che stiamo cercando qui? –

37

Speriamo che questo aiuta:

>>> seta = set('1234') 
>>> listb = ['a','b','c'] 
>>> seta.union(listb) 
set(['a', 'c', 'b', '1', '3', '2', '4']) 
>>> seta 
set(['1', '3', '2', '4']) 
>>> seta = seta.union(listb) 
>>> seta 
set(['a', 'c', 'b', '1', '3', '2', '4']) 
3

Ecco come faccio di solito è:

def add_list_to_set(my_list, my_set): 
    [my_set.add(each) for each in my_list] 
return my_set 
25

Per aggiungere gli elementi di una lista ad un insieme, utilizzare update

https://docs.python.org/2/library/sets.html

s.update (t): ritorno insieme s con elementi aggiunti da t

Ad es

>>> s = set([1, 2]) 
>>> l = [3, 4] 
>>> s.update(l) 
>>> s 
{1, 2, 3, 4} 

Se si desidera invece aggiungere l'intero elenco come un unico elemento al set, non è possibile perché le liste non sono hashable. Potresti invece aggiungere una tupla, ad es. s.add(tuple(l)). Vedi anche TypeError: unhashable type: 'list' when using built-in set function per maggiori informazioni al riguardo.

-1

Questo dovrebbe fare:

set(tuple(i) for i in L)