325

在 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 无法判断我是否两次添加了相同的列表。有解决方法吗?

编辑:我想添加列表本身,而不是它的元素。

4

12 回答 12

777

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

编辑:如果您想添加列表本身而不是其成员,那么不幸的是,您必须使用元组。集合成员必须是可散列的

于 2009-08-20T14:41:46.173 回答
243

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

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

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

编辑:一些解释:文档将 a 定义set不同的可散列对象的无序集合。对象必须是可散列的,以便查找、添加和删除元素比每次执行这些操作时查看每个单独的元素更快。使用的具体算法在Wikipedia 文章中进行了解释。Python 散列算法在effbot.orgpython 参考__hash__中的 python 函数中进行了解释。

一些事实:

  • 集合元素字典键必须是可散列的
  • 一些不可散列的数据类型:
    • list:tuple改用
    • set:frozenset改用
    • dict: 没有官方对应,但有一些 食谱
  • 默认情况下,对象实例是可散列的,每个实例都有唯一的散列。您可以按照 python 参考中的说明覆盖此行为。
于 2009-08-20T14:39:51.057 回答
93

要将列表的元素添加到集合中,请使用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' when using built-in set function了解更多信息。

于 2017-05-02T20:01:02.873 回答
45

希望这会有所帮助:

>>> 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'])
于 2013-08-23T09:24:30.270 回答
17

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

用它自己和其他人的并集更新一个集合。

于 2012-05-05T12:01:53.420 回答
9

列表对象是不可散列的。你可能想把它们变成元组。

于 2009-08-20T14:43:17.900 回答
7

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

因为集合是可变的,所以你不能有集合!不过,您可以拥有一组frozensets。

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

其他答案已经给了你代码,我希望这能给你一些见解。我希望 Alex Martelli 能回答更多细节。

于 2009-08-20T14:47:53.090 回答
6

我发现我今天需要做类似的事情。该算法知道何时创建需要添加到集合中的新列表,但不知道何时完成对列表的操作。

无论如何,我想要的行为是 set to useid而不是hash. 因此,我发现mydict[id(mylist)] = mylist而不是myset.add(mylist)提供我想要的行为。

于 2011-03-23T17:33:48.960 回答
5

你想添加一个元组,而不是一个列表:

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

如果有列表,可以转换成元组,如上图。元组是不可变的,因此可以添加到集合中。

于 2009-08-20T14:47:02.543 回答
4

你会想要使用可散列的元组(你不能散列一个像列表这样的可变对象)。

>>> 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')])
于 2009-08-20T14:45:08.100 回答
4

尝试使用*解包,如下所示:

>>> a=set('abcde')
>>> a
{'a', 'd', 'e', 'b', 'c'}
>>> l=['f','g']
>>> l
['f', 'g']
>>> {*l, *a}
{'a', 'd', 'e', 'f', 'b', 'g', 'c'}
>>> 

非编辑器版本:

a=set('abcde')
l=['f', 'g']
print({*l, *a})

输出:

{'a', 'd', 'e', 'f', 'b', 'g', 'c'}
于 2020-12-23T09:20:17.520 回答
3

以下是我通常的做法:

def add_list_to_set(my_list, my_set):
    [my_set.add(each) for each in my_list]
return my_set
于 2014-02-19T07:26:42.667 回答