Добавить список для установки?

242

Проверено на интерпретаторе 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

Я думаю, что не могу добавить список к набору, потому что Python никак не может сказать, добавил ли я один и тот же список дважды. Есть ли обходной путь?

РЕДАКТИРОВАТЬ: Я хочу добавить сам список, а не его элементы.

Адам Матан
источник
2
Вы хотите добавить список в набор или элементы в списке?
PKIT
Сам список - я хочу иметь набор списков.
Адам Матан
Кажется, лучше всего подходит недооцененный ответ, предлагающий использовать aSet.add (id (lst)) перед добавлением самого lst в какой-либо список / очередь / и т. Д., Чтобы убедиться, что вы это сделали. Вам следует пересмотреть принятый ответ.
Рустам А.

Ответы:

187

Вы не можете добавить список в набор, потому что списки изменчивы, это означает, что вы можете изменить содержимое списка после добавления его в набор.

Однако вы можете добавить кортежи к набору, потому что вы не можете изменить содержимое кортежа:

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

Редактировать : некоторые пояснения: документация определяет setкак неупорядоченную коллекцию различных хешируемых объектов. Объекты должны быть хешируемыми, чтобы поиск, добавление и удаление элементов можно было выполнять быстрее, чем просмотр каждого отдельного элемента каждый раз, когда вы выполняете эти операции. Конкретные алгоритмы описаны в статье в Википедии . Алгоритмы хеширования Pythons описаны на effbot.org и __hash__функции pythons в справочнике по python .

Некоторые факты:

  • Элементы набора, а также ключи словаря должны быть хэшируемыми
  • Некоторые небрежные типы данных:
    • list: используйте tupleвместо
    • set: используйте frozensetвместо
    • dict: не имеет официального аналога, но есть некоторые рецепты
  • По умолчанию экземпляры объектов могут быть хэшируемыми, каждый экземпляр имеет уникальный хэш. Вы можете переопределить это поведение, как описано в ссылке на Python.
Отто Альмендингер
источник
6
И если вы хотите добавить набор в набор, используйте frozenset.
FogleBird
4
collections.namedtupleможно считать «официальным» аналогом dict.
SilentGhost
1
@Wahnfrieden: это добавление содержимого набора, а не самого набора.
Отто Allmendinger
@aehlke: Нет, это добавляет элементы набора в первый набор, но мы говорим о добавлении набора в качестве элемента первого набора.
Джефф Лирман
578

использование set.update() или|=

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

редактировать: если вы хотите добавить сам список, а не его членов, то, к сожалению, вы должны использовать кортеж. Набор участников должен быть хэшируемым .

aehlke
источник
set.update () добавляет список в набор, правильно? для чего нужен оператор "труба"?
FistOfFury
Что касается множеств, |оператор реализует операцию объединения множеств . И |=оператор, и set.update()метод применяют эту операцию на месте и фактически являются синонимами. Таким образом, set_a |= set_bможно считать синтаксический сахар для обоих set_a.update(set_b) и set_a = set_a | set_b (за исключением того, что в последнем случае один и тот же set_aобъект используется повторно, а не переназначается). </ahem>
Сесил Карри
76

Чтобы добавить элементы списка в набор , используйтеupdate

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

s.update (t): вернуть набор s с элементами, добавленными из t

Например

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

Если вместо этого вы хотите добавить весь список как один элемент в набор, вы не сможете этого сделать, потому что списки не могут быть хешируемыми. Вместо этого вы можете добавить кортеж, например s.add(tuple(l)). Смотрите также TypeError: unhashable type: 'list' при использовании встроенной функции set для получения дополнительной информации об этом.

JDiMatteo
источник
40

Надеюсь, это поможет:

>>> 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
источник
15

Пожалуйста, обратите внимание на функцию set.update(). Документация гласит:

Обновите набор с союзом себя и других.

eggfly
источник
5
Это не отвечает на вопрос (так как ОП хочет добавить сам список в набор), но это был ответ, который мне был нужен, когда Google привел меня сюда :-)
Том Страттон
1
Ну, мне кажется, что это наиболее актуальный ответ на вопрос ... например, если b = set ([1]), b.update ([7,25]) даст b следующее значение: set ([ 1, 25, 7]) ---> Разве это не то, что мы ищем здесь?
Луи ЛК
8

Список объектов не подлежит изменению . Вы могли бы хотеть превратить их в кортежи все же.

SilentGhost
источник
5

Наборы не могут иметь изменяемые (изменяемые) элементы / элементы. Список, будучи изменяемым, не может быть членом набора.

Поскольку наборы изменчивы, вы не можете иметь наборы! Вы можете иметь набор Frozensets, хотя.

(То же самое «требование изменчивости» применяется к ключам dict.)

Другие ответы уже дали вам код, надеюсь, это даст немного понимания. Я надеюсь, что Алекс Мартелли ответит еще более подробно.

user135331
источник
4

Вы хотите добавить кортеж, а не список:

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

Если у вас есть список, вы можете преобразовать его в кортеж, как показано выше. Кортеж неизменен, поэтому его можно добавить в набор.

hughdbrown
источник
4

Я обнаружил, что мне нужно сделать что-то подобное сегодня. Алгоритм знал, когда он создает новый список, который необходимо добавить в набор, но не когда он закончил работу со списком.

Во всяком случае, поведение, которое я хотел, было для использования, idа не для hash. Таким образом, я нашел mydict[id(mylist)] = mylistвместо того, myset.add(mylist)чтобы предлагать поведение, которое я хотел.

Дюны
источник
3

Вы захотите использовать кортежи, которые можно хэшировать (вы не можете хэшировать изменяемый объект, например список).

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

Вот как я обычно это делаю:

def add_list_to_set(my_list, my_set):
    [my_set.add(each) for each in my_list]
return my_set
Kashif
источник
-4

Это должно сделать:

set(tuple(i) for i in L)
WQS
источник