2009-08-20 11 views
141

Probado en Python 2.6 intérprete:Python: ¿Agregar lista para establecer?

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

Creo que no puedo añadir la lista para el conjunto, porque no hay manera de Python puede decir si he añadido la misma lista dos veces. ¿Hay alguna solución?

EDITAR: Quiero agregar la lista en sí, no sus elementos.

+2

¿Quieres añadir la lista para el juego o los elementos de la lista? – pkit

+0

La lista en sí misma: quiero tener un conjunto de listas. –

+0

Luego usa la opción de tupla que Otto respondió. – pkit

Respuesta

131

No se puede agregar una lista a un conjunto porque las listas son mutables, lo que significa que puede cambiar los contenidos de la lista después de agregarla al conjunto.

Sin embargo, puede añadir tuplas al conjunto, porque no se puede cambiar el contenido de una tupla:

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

Editar: una explicación: La documentación define un set como una colección desordenada de distintos objetos lavables. Los objetos tienen que ser aptos para que encontrar, agregar y quitar elementos se pueda hacer más rápido que mirar cada elemento individual cada vez que realice estas operaciones. Los algoritmos específicos utilizados se explican en el Wikipedia article. Los algoritmos hash de Pitones se explican en effbot.org y las pitones __hash__ funcionan en el python reference.

Algunos datos:

  • Fije los elementos así como claves de diccionario tienen que ser hashable
  • Algunos tipos de datos unhashable:
    • list: utilizar tuple lugar
    • set: use frozenset en su lugar
    • dict: no tiene contraparte oficial, pero hay algunas recipes
  • casos son objeto hashable por defecto con cada instancia tiene un hash único. Puede anular este comportamiento como se explica en la referencia de python.
+4

Y si alguna vez desea agregar un conjunto a un conjunto, use frozenset. – FogleBird

+4

['collections.namedtuple'] (http://docs.python.org/library/collections.html#collections.namedtuple) se puede considerar una contraparte" oficial "del' dict'. – SilentGhost

+2

@FogleBird o el operador de unión: | = – aehlke

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

operador La unión es mucho más rápido que añadir todos modos.

editar: Si quieres la lista en sí y no sus miembros, entonces debes usar una tupla, desafortunadamente. Los miembros del set deben ser manejables.

+20

'a.update (l)' tiene el mismo efecto. –

8

Los objetos de la lista son instátiles. es posible que desee convertirlos en tuplas sin embargo.

3

Te conviene utilizar tuplas, que son hashable (no se puede hash un objeto mutable como 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

Guau, escribimos casi exactamente lo mismo al mismo tiempo. – hughdbrown

4

desea agregar una tupla, no 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')]) 

Si usted tiene una lista, puede convertir a la tupla, como se muestra arriba. Una tupla es inmutable, por lo que se puede agregar al conjunto.

+0

no necesita 'tuple (x para x en l)', puede hacer: 'tuple (l)' – SilentGhost

+0

Ah, correcto. Tengo una sintaxis de comprensión escrita en mis dedos. – hughdbrown

4

Los conjuntos no pueden tener elementos/miembros mutables (modificables). Una lista, al ser mutable, no puede ser miembro de un conjunto.

¡Como los conjuntos son mutables, no puede tener un conjunto de conjuntos! Aunque puede tener un conjunto de conjuntos congelados.

(El mismo tipo de "requisito mutabilidad" se aplica a las teclas de un dict.)

Otras respuestas ya han dado su código, espero que esto da un poco de perspicacia. Espero que Alex Martelli responda con más detalles.

2

Encontré que necesitaba hacer algo similar hoy. El algoritmo sabía cuándo estaba creando una nueva lista que necesitaba agregarse al conjunto, pero no cuándo habría terminado de funcionar en la lista.

De todos modos, el comportamiento que quería era para el conjunto para usar id en lugar de hash. Como tal, encontré mydict[id(mylist)] = mylist en lugar de myset.add(mylist) para ofrecer el comportamiento que quería.

13

Tenga en cuenta la función set.update(). La documentación dice:

Actualiza un conjunto con la unión de sí mismo y otros.

+5

Esto no responde la pregunta (ya que el OP quiere agregar la lista al conjunto) pero fue la respuesta que necesitaba cuando Google me trajo aquí :-) –

+1

Bueno, parece ser la respuesta más relevante al pregunta para mí ... por ejemplo, si b = set ([1]), b.update ([7,25]) le dará a b el siguiente valor: set ([1, 25, 7]) ---> ¿No es eso lo que estamos buscando aquí? –

37

Esperemos que esto ayuda:

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

Así es como normalmente lo hago:

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

Para añadir los elementos de una lista a un conjunto, utilice update

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

s.update (t): retorno conjunto s con elementos añadidos de t

P. ej

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

Si por el contrario quiere añadir toda la lista como un único elemento al conjunto, que no puede porque no están listas hashable. En su lugar, podría agregar una tupla, p. s.add(tuple(l)). Consulte también TypeError: unhashable type: 'list' when using built-in set function para obtener más información al respecto.

-1

Esto debería hacer:

set(tuple(i) for i in L) 
Cuestiones relacionadas