添加列表进行设置?


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

列表本身-我想要一组列表。
亚当·马坦

似乎最合适的答案是被低估的答案,建议在将lst自身添加到某些列表/队列/等之前使用aSet.add(id(lst)),以确保您确实执行了此操作。您应该重新考虑接受的答案。
Rustam A.

Answers:


187

您不能将列表添加到集合中,因为列表是可变的,这意味着您可以在将列表添加到集合后更改列表的内容。

但是,您可以将元组添加到集合中,因为您不能更改元组的内容:

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

编辑:某些解释:文档将a定义set不同的可哈希对象的无序集合。这些对象必须是可哈希化的,因此,与每次执行这些操作时都要查看每个单独的元素相比,查找,添加和删除元素可以更快地完成。Wikipedia文章中说明了使用的特定算法。在effbot.org上说明了Python的哈希算法,并且__hash__python参考中提供了pythons函数。

一些事实:

  • 设置元素以及字典键必须是可哈希的
  • 一些不可散列的数据类型:
    • listtuple改用
    • setfrozenset改用
    • dict:没有官方对应文件,但有一些 食谱
  • 默认情况下,对象实例是可哈希的,每个实例具有唯一的哈希。您可以按照python参考中的说明覆盖此行为。

6
而且,如果您要向集合中添加集合,请使用Frozenset。
2009年

4
collections.namedtuple可能被视为的“官方”对应物dict
SilentGhost

1
@Wahnfrieden:即添加集合的内容,而不是集合本身。
奥托·

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

编辑:如果要添加列表本身而不是其成员,那么很遗憾,您必须使用元组。集合成员必须是可哈希的


set.update()将列表添加到集合中,对吗?管道等于运算符的作用是什么?
FistOfFury

关于集合,|操作员执行集合联合操作。无论是|=运营商和set.update()方法适用于就地该操作,并有效的代名词。因此,set_a |= set_b对于set_a.update(set_b) ,都可以被视为语法糖set_a = set_a | set_b(除了在后一种情况下,相同的set_a对象被重用而不是重新分配)。</ahem>
Cecil Curry

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:无法散列的类型:“ list”(在使用内置set函数时)


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

15

请注意该功能set.update()。该文档说:

用本身和其他元素的并集更新集合。


5
这没有回答问题(因为OP希望将列表本身添加到集合中),但这是Google将我带到这里时我需要的答案:-)
tom stratton

1
好吧,这似乎是对我来说问题最相关的答案……例如,如果b = set([1]),b.update([7,25])将给b以下值:set([ 1,25,7])--->这不是我们在这里寻找的东西吗?
路易LC


5

集合不能具有可变的(可变的)元素/成员。可变列表不能成为集合的成员。

由于集合是可变的,因此不能有集合!但是,您可以设置一组Frozensets。

(同一种“可变性要求”适用于字典的键。)

其他答案已经为您提供了代码,我希望这能提供一些见识。我希望Alex Martelli会提供更多详细信息。


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

如果有列表,则可以转换为元组,如上所示。元组是不可变的,因此可以将其添加到集合中。


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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.