Python: Добавить список для установки? - PullRequest
189 голосов
/ 20 августа 2009

Проверено на интерпретаторе 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 никак не может сказать, добавил ли я один и тот же список дважды. Есть ли обходной путь?

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

Ответы [ 12 ]

427 голосов
/ 20 августа 2009

Использование 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'}

edit: Если вы хотите добавить сам список, а не его членов, то, к сожалению, вы должны использовать кортеж. Члены набора должны быть hashable .

157 голосов
/ 20 августа 2009

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

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

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

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

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

  • Набор элементов , а также словарные ключи должны быть хэшируемыми
  • Некоторые небезопасные типы данных:
    • list: используйте tuple вместо
    • set: используйте frozenset вместо
    • dict: не имеет официального аналога, но есть некоторые 1042 * рецепты *
  • Экземпляры объектов по умолчанию являются хэшируемыми, каждый экземпляр имеет уникальный хэш. Вы можете переопределить это поведение, как описано в ссылке на Python.
66 голосов
/ 02 мая 2017

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

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

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

* 1013 Е.Г. *

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

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

39 голосов
/ 23 августа 2013

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

>>> 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'])
14 голосов
/ 05 мая 2012

Обратите внимание на функцию set.update(). В документации сказано:

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

8 голосов
/ 20 августа 2009

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

5 голосов
/ 20 августа 2009

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

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

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

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

4 голосов
/ 20 августа 2009

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

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

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

3 голосов
/ 23 марта 2011

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

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

3 голосов
/ 20 августа 2009

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

>>> 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')])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...