Python:添加列表来设置?

Python: Add list to set?

在python 2.6解释器上测试:

1
2
3
4
5
6
7
8
9
10
11
>>> 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就无法判断。有解决办法吗?

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


使用set.update()|=

1
2
3
4
5
6
7
8
9
10
>>> 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'}

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


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

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

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

编辑:一些解释:文档将set定义为不同哈希对象的无序集合。对象必须是可散列的,这样查找、添加和删除元素的速度就可以比每次执行这些操作时查看每个单独的元素的速度更快。维基百科文章解释了使用的具体算法。pythons散列算法在effbot.org和pythons __hash__函数的pythons参考中进行了解释。

一些事实:

  • 集合元素和字典键必须是可哈希的
  • 某些不可显示的数据类型:
    • list:用tuple代替
    • set:用frozenset代替
    • dict:没有官方对应,但有一些食谱
    • 小精灵

    • 对象实例在默认情况下是可以散列的,每个实例都有一个唯一的散列。您可以按照python引用中的说明重写此行为。
    • 小精灵


      要将列表元素添加到集合中,请使用update

      来自https://docs.python.org/2/library/sets.html

      s.update(t): return set s with elements added from t

      例如。

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

      如果您希望将整个列表作为单个元素添加到集合中,则不能这样做,因为列表是不可哈希的。您可以添加一个元组,例如s.add(tuple(l))。另请参见typeerror:unhashible类型:使用内置set函数时的"list",以获取有关该类型的详细信息。


      希望这有助于:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      >>> 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'])

      请注意函数set.update()。文件上说:

      Update a set with the union of itself and others.


      列表对象不可显示。不过,您可能想将它们转换成元组。


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

      因为集合是可变的,所以不能有集合!不过,你可以有一套冰冻的。

      (同样的"可变性要求"也适用于口述的按键。)

      其他答案已经给了你代码,我希望这能给你一点启发。我希望亚历克斯·马泰利能更详细地回答。


      要添加元组,而不是列表:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      >>> 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')])

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


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

      不管怎样,我想要的行为是使用id而不是hash。因此,我发现mydict[id(mylist)] = mylist而不是myset.add(mylist)提供了我想要的行为。


      您将要使用可散列的元组(不能散列列表之类的可变对象)。

      1
      2
      3
      4
      5
      6
      7
      >>> 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')])

      我通常是这样做的:

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


      应该这样做:

      1
      set(tuple(i) for i in L)