Añadir lista para establecer?

242

Probado en el intérprete Python 2.6:

>>> 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 agregar la lista al conjunto porque no hay forma de que Python pueda saber si he agregado la misma lista dos veces. ¿Hay alguna solución?

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

Adam Matan
fuente
2
¿Desea agregar la lista al conjunto o los elementos de la lista?
pkit
La lista en sí: quiero tener un conjunto de listas.
Adam Matan
Parece que la respuesta más adecuada es la subestimada, que sugiere usar aSet.add (id (lst)) antes de agregar lst a alguna lista / cola / etc, para asegurarse de que lo hizo. Debería reconsiderar la respuesta aceptada.
Rustam A.

Respuestas:

187

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

Sin embargo, puede agregar tuplas al conjunto, porque no puede cambiar el contenido de una tupla:

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

Editar : alguna explicación: La documentación define a setcomo una colección desordenada de distintos objetos que se pueden compartir. Los objetos tienen que ser intercambiables para poder encontrar, agregar y eliminar elementos más rápido que mirar cada elemento individual cada vez que realice estas operaciones. Los algoritmos específicos utilizados se explican en el artículo de Wikipedia . Los algoritmos de hash de Pythons se explican en effbot.org y la __hash__función de pythons en la referencia de python .

Algunos hechos:

  • Los elementos de configuración , así como las teclas de diccionario, deben ser hashable
  • Algunos tipos de datos no compartibles:
    • list: utilizar tupleen su lugar
    • set: utilizar frozenseten su lugar
    • dict: no tiene contraparte oficial, pero hay algunas recetas
  • Las instancias de objeto son hash de forma predeterminada con cada instancia que tiene un hash único. Puede anular este comportamiento como se explica en la referencia de Python.
Otto Allmendinger
fuente
66
Y si alguna vez desea agregar un conjunto a un conjunto, use frozenset.
FogleBird
44
collections.namedtuplepodría considerarse contraparte "oficial" de la dict.
SilentGhost
1
@Wahnfrieden: eso es agregar el contenido de un conjunto, no el conjunto en sí.
Otto Allmendinger
@aehlke: No, eso agrega los elementos del conjunto al primer conjunto, pero estamos hablando de agregar un conjunto como elemento del primer conjunto.
Jeff Learman
578

Use set.update()o|=

>>> a = set('abc')
>>> l = ['d', 'e']
>>> a.update(l)
>>> a
{'e', 'b', 'c', 'd', 'a'}

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

editar: si desea agregar la lista en sí y no sus miembros, desafortunadamente debe usar una tupla. Los miembros del conjunto deben ser hashable .

aehlke
fuente
set.update () agrega la lista al conjunto, ¿correcto? ¿Para qué sirve el operador de tubería igual?
FistOfFury
Con respecto a los conjuntos, el |operador implementa la operación de unión de conjuntos . Tanto el |=operador como el set.update()método aplican esa operación en el lugar y son efectivamente sinónimos. Por lo tanto, set_a |= set_bpodría considerarse azúcar sintáctico para ambos set_a.update(set_b) y set_a = set_a | set_b (excepto que en el último caso, el mismo set_aobjeto se reutiliza en lugar de reasignarse). </ahem>
Cecil Curry
76

Para agregar los elementos de una lista a un conjunto , useupdate

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

s.update (t): devuelve el conjunto s con elementos agregados desde t

P.ej

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

Si, en cambio, desea agregar la lista completa como un elemento único al conjunto, no puede hacerlo porque las listas no se pueden compartir. En su lugar, podría agregar una tupla, por ejemplo s.add(tuple(l)). Consulte también TypeError: tipo no compartible: 'lista' cuando se utiliza la función de conjunto incorporada para obtener más información al respecto.

JDiMatteo
fuente
40

Esperemos que esto ayude:

>>> 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'])
alvas
fuente
15

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

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

mosca del huevo
fuente
55
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í :-)
Tom Stratton
1
Bueno, me parece la respuesta más relevante a la pregunta ... por ejemplo, si b = set ([1]), b.update ([7,25]) le dará a b el siguiente valor: set ([ 1, 25, 7]) ---> ¿No es lo que estamos buscando aquí?
Louis LC
8

Los objetos de la lista no son compartibles . Sin embargo, es posible que desee convertirlos en tuplas.

SilentGhost
fuente
5

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! Sin embargo, puedes tener un conjunto de congelados.

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

Otras respuestas ya le han dado el código, espero que esto le dé un poco de información. Espero que Alex Martelli responda con aún más detalles.

usuario135331
fuente
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 tiene una lista, puede convertirla a la tupla, como se muestra arriba. Una tupla es inmutable, por lo que se puede agregar al conjunto.

hughdbrown
fuente
4

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

De todos modos, el comportamiento que quería era usarlo en idlugar de hacerlo hash. Como tal, encontré en mydict[id(mylist)] = mylistlugar de myset.add(mylist)ofrecer el comportamiento que quería.

Dunas
fuente
3

Querrás usar tuplas, que son hash (no puedes hacer un hash con 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')])
Noé
fuente
2

Así es como lo hago habitualmente:

def add_list_to_set(my_list, my_set):
    [my_set.add(each) for each in my_list]
return my_set
kashif
fuente
-4

Esto debería hacer:

set(tuple(i) for i in L)
WQS
fuente