【问题标题】:Add list to set?添加要设置的列表?
【发布时间】:2010-11-21 08:30:26
【问题描述】:

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

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

【问题讨论】:

  • 您要将列表添加到集合还是列表中的项目?
  • 列表本身 - 我想要一组列表。
  • 似乎最适合的答案是被低估的答案,建议在将 lst 本身添加到某些列表/队列/等之前使用 aSet.add(id(lst)) ,以确保您做到了.您应该重新考虑接受的答案。

标签: python list python-2.7 set


【解决方案1】:

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

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

【讨论】:

  • set.update() 将列表添加到集合中,对吗?管道等于运算符的用途是什么?
  • 对于集合,| 运算符实现了set union operation|= 运算符和 set.update() 方法都在原地应用该操作并且实际上是同义词。因此,set_a |= set_b 可以被视为set_a.update(set_b) set_a = set_a | set_b 的语法糖(除了在后一种情况下,相同的set_a 对象被重用而不是重新分配)。 &lt;/ahem&gt;
【解决方案2】:

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

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

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

编辑:一些解释:文档将set 定义为不同的可散列对象的无序集合。对象必须是可散列的,以便查找、添加和与每次执行这些操作时查看每个单独的元素相比,删除元素可以更快地完成。使用的具体算法在Wikipedia article 中有说明。 Python 的哈希算法在 effbot.org 和 Python 的 __hash__ 函数中在 python reference 中进行了解释。

一些事实:

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

【讨论】:

  • 如果您想将一个集合添加到集合中,请使用 freezeset。
  • collections.namedtuple 可能被认为是dict 的“官方”对应物。
  • @Wahnfrieden:那是添加集合的 contents,而不是集合本身。
  • @aehlke:不,这会将集合的元素添加到第一个集合中,但我们正在讨论添加一个集合作为第一个集合的元素。
  • 也许OrdereDict 适用于dict 案例?来自collections 库?
【解决方案3】:

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

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

s.update(t):返回从 t​​ 添加元素的集合 s

例如

>>> 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

【讨论】:

    【解决方案4】:

    希望这会有所帮助:

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • 这没有回答问题(因为 OP 想要将列表本身添加到集合中),但这是我在 Google 将我带到这里时需要的答案 :-)
      • 嗯,对我来说,这似乎是对这个问题最相关的答案......例如,如果 b = set([1]), b.update([7,25]) 将给出b 以下值:set([1, 25, 7]) ---> 这不是我们要在这里寻找的吗?
      【解决方案6】:

      列表对象是不可散列的。不过,您可能希望将它们转换为元组。

      【讨论】:

        【解决方案7】:

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

        由于集合是可变的,所以你不能有集合! 不过你可以有一套frozensets。

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

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

        【讨论】:

          【解决方案8】:

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

          无论如何,我想要的行为是设置为使用id 而不是hash。因此,我找到了 mydict[id(mylist)] = mylist 而不是 myset.add(mylist) 来提供我想要的行为。

          【讨论】:

            【解决方案9】:

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

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

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

            【讨论】:

              【解决方案10】:

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

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

              【讨论】:

                【解决方案11】:

                这是我通常的做法:

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

                【讨论】:

                  【解决方案12】:

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

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

                  【讨论】:

                  • 似乎 OP 需要创建一组列表。您的解决方案将创建一组元素。我不认为它们是相同的东西。在您的示例中,如果l 等于['f', 'g', 'a'],则解包l 将丢失a
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-05-01
                  相关资源
                  最近更新 更多