Dodaj listę do ustawienia?


242

Testowane na interprecie języka 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

Myślę, że nie mogę dodać listy do zestawu, ponieważ nie ma możliwości, aby Python mógł stwierdzić, czy dodałem tę samą listę dwa razy. Czy jest w pobliżu praca?

EDYCJA: Chcę dodać samą listę, a nie jej elementy.


2
Czy chcesz dodać listę do zestawu lub elementów na liście?
pkit

Sama lista - chcę mieć zestaw list.
Adam Matan,

Wydaje się, że najlepiej pasującą odpowiedzią jest niedoceniana, sugerująca użycie aSet.add (id (lst)) przed dodaniem samego lst do jakiejś listy / kolejki / itp., Aby mieć pewność, że to zrobiłeś. Powinieneś ponownie rozważyć zaakceptowaną odpowiedź.
Rustam A.

Odpowiedzi:


187

Nie można dodać listy do zestawu, ponieważ listy można modyfikować, co oznacza, że ​​można zmienić zawartość listy po dodaniu jej do zestawu.

Możesz jednak dodać krotki do zestawu, ponieważ nie możesz zmienić zawartości krotki:

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

Edycja : niektóre wyjaśnienia: Dokumentacja definiuje setjako nieuporządkowany zbiór różnych obiektów możliwych do skrótu. Obiekty muszą być haszowalne, aby wyszukiwanie, dodawanie i usuwanie elementów odbywało się szybciej niż patrzenie na każdy element za każdym razem, gdy wykonujesz te operacje. Konkretne zastosowane algorytmy wyjaśniono w artykule w Wikipedii . Algorytmy mieszające Pythona są wyjaśnione na stronie effbot.org, a __hash__funkcja pytonów w odnośniku do Pythona .

Kilka faktów:

  • Elementy zestawu, a także klawisze słownika muszą być haszowalne
  • Niektóre typy danych nie do opanowania:
    • list: użyj tuplezamiast tego
    • set: użyj frozensetzamiast tego
    • dict: nie ma oficjalnego odpowiednika, ale istnieją pewne przepisy
  • Instancje obiektów są domyślnie mieszalne, a każde wystąpienie ma unikalny skrót. Możesz zastąpić to zachowanie, jak wyjaśniono w dokumentacji Pythona.

6
A jeśli kiedykolwiek chcesz dodać zestaw do zestawu, użyj frozenset.
FogleBird,

4
collections.namedtuplemoże być uważany za „oficjalny” odpowiednik dict.
SilentGhost,

1
@Wahnfrieden: to dodaje zawartość zestawu, a nie sam zestaw.
Otto Allmendinger,

@aehlke: Nie, to dodaje elementy zestawu do pierwszego zestawu, ale mówimy o dodaniu zestawu jako elementu pierwszego zestawu.
Jeff Learman

578

Użyj set.update()lub|=

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

edycja: Jeśli chcesz dodać samą listę, a nie jej członków, musisz niestety użyć krotki. Członkowie zestawu muszą mieć funkcję skrótu .


set.update () dodaje listę do zestawu, prawda? do czego służy rura równa się operatorowi?
FistOfFury

W odniesieniu do zestawów |operator realizuje operację łączenia zestawów . Zarówno |=operator, jak i set.update()metoda stosują tę operację w miejscu i są skutecznie synonimami. Tak więc, set_a |= set_bmożna uznać zarówno za cukier syntaktyczny set_a.update(set_b) i set_a = set_a | set_b (chyba że w tym ostatnim przypadku, ten sam set_aobiekt jest wykorzystywany zamiast przeniesiony). </ahem>
Cecil Curry

76

Aby dodać elementy listy do zestawu , użyjupdate

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

s.update (t): zwraca zestaw s z elementami dodanymi z t

Na przykład

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

Jeśli zamiast tego chcesz dodać całą listę jako pojedynczy element do zestawu, nie możesz tego zrobić, ponieważ listy nie są mieszalne. Zamiast tego możesz dodać krotkę, np s.add(tuple(l)). Zobacz także TypeError: unhashable type: 'list', gdy używasz wbudowanej funkcji set, aby uzyskać więcej informacji na ten temat.


40

Mam nadzieję, że to pomaga:

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

Proszę zwrócić uwagę na funkcję set.update(). Dokumentacja mówi:

Zaktualizuj zestaw, łącząc siebie i innych.


5
To nie odpowiada na pytanie (ponieważ OP chce dodać samą listę do zestawu), ale była to odpowiedź, której potrzebowałem, kiedy Google mnie tu przyprowadził :-)
Tom Stratton

1
Cóż, wydaje mi się, że jest to najbardziej odpowiednia odpowiedź na pytanie ... na przykład, jeśli b = set ([1]), b. Aktualizacja ([7,25]) da b następującą wartość: set ([ 1, 25, 7]) ---> Czy nie tego tu szukamy?
Louis LC,


5

Zestawy nie mogą mieć zmiennych / zmiennych elementów / elementów. Zmodyfikowana lista nie może być członkiem zestawu.

Ponieważ zestawy są zmienne, nie możesz mieć zestawu zestawów! Możesz jednak mieć zestaw frozensetów.

(Ten sam rodzaj „wymogu zmienności” dotyczy kluczy dykta).

Inne odpowiedzi już dały ci kod, mam nadzieję, że daje to trochę wglądu. Mam nadzieję, że Alex Martelli odpowie jeszcze bardziej szczegółami.


4

Chcesz dodać krotkę, a nie listę:

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

Jeśli masz listę, możesz przekonwertować na krotkę, jak pokazano powyżej. Krotka jest niezmienna, więc można ją dodać do zestawu.


4

Odkryłem, że muszę dziś zrobić coś podobnego. Algorytm wiedział, kiedy tworzy nową listę, którą należy dodać do zestawu, ale nie wie, kiedy przestanie działać na liście.

W każdym razie zachowanie, którego chciałem, było idraczej zgodne z zestawem hash. Jako taki znalazłem mydict[id(mylist)] = mylistzamiast myset.add(mylist)oferować zachowanie, które chciałem.


3

Będziesz chciał użyć krotek, które są haszowalne (nie możesz haszować zmiennego obiektu, takiego jak 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

Oto jak zwykle to robię:

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.