2009-08-20 2 views
141

Испытаны на Python 2.6 переводчика:Python: Добавить список для установки?

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

EDIT: Я хочу добавить сам список, а не его элементы.

+2

Хотите добавить список в набор или элементов в списке? – pkit

+0

Сам список - я хочу иметь набор списков. –

+0

Затем используйте опцию кортежа, на которую ответил Отто. – pkit

ответ

131

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

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

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

Edit: некоторые пояснения: Документация определяет set как неупорядоченный сбор различных хешируемых объектов. Объекты должны быть хешируемыми, так что поиск, добавление и удаление элементов может выполняться быстрее, чем просмотр каждого отдельного элемента каждый раз, когда вы выполняете эти операции. Используемые конкретные алгоритмы объясняются в Wikipedia article. Алгоритмы хеширования Pythons объясняются на effbot.org и питонах __hash__ в python reference.

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

  • Набор элементов, а также ключи словаря должны быть hashable
  • Некоторые unhashable типы данных:
    • list: использовать tuple вместо
    • set: используйте frozenset вместо
    • dict: не имеет официального двойника, но есть некоторые recipes
  • экземпляры объектов hashable по умолчанию с каждым экземпляром, имеющие уникальный хэш. Вы можете переопределить это поведение, как описано в ссылке на python.
+4

И если вы хотите добавить набор в набор, используйте frozenset. – FogleBird

+4

['collections.namedtuple'] (http://docs.python.org/library/collections.html#collections.namedtuple) можно считать« официальным »аналогом« dict ». – SilentGhost

+2

@FogleBird или оператор объединения: | = – aehlke

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

оператор Союз гораздо быстрее, чем добавлять в любом случае.

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

+20

'a.update (l)' имеет тот же эффект. –

8

объекты в списке расщепляются. вы можете захотеть включить их в кортежи.

3

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

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

Вау, мы писали почти то же самое в одно и то же время. – hughdbrown

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

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

+0

вам не нужно 'tuple (x for x in l)', вы можете просто сделать: 'tuple (l)' – SilentGhost

+0

А, правильно. У меня есть список синтаксиса понимания, застрявшего в моих пальцах. – hughdbrown

4

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

Поскольку комплекты изменяемы, вы не можете иметь набор наборов! У вас может быть набор фризонов.

(Тот же самый вид «требование Изменчивость» относится к клавишам Dict.)

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

2

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

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

13

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

Обновите комплект с помощью соединения самого себя и других.

+5

Это не отвечает на вопрос (поскольку OP хочет добавить сам список к набору), но это был тот ответ, который мне нужен, когда Google привел меня сюда :-) –

+1

Ну, это похоже на самый важный ответ на вопрос вопрос для меня ... например, если b = set ([1]), b.update ([7,25]) даст b следующее значение: set ([1, 25, 7]) ---> Разве это не то, что мы ищем здесь? –

37

Надеется, что это помогает:

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

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

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

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

От https://docs.python.org/2/library/sets.html

s.update (т): возвращаемый набор с элементами добавленных из т

Е.Г.

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

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

-1

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

set(tuple(i) for i in L) 

 Смежные вопросы

  • Нет связанных вопросов^_^