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.


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.

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 .


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.


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'])

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.


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.


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.


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.


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.


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')])

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

-4

Esto debería hacer:

set(tuple(i) for i in L)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.