【问题标题】:Understanding the set() function理解 set() 函数
【发布时间】:2013-03-03 02:39:27
【问题描述】:

在 python 中,set() 是一个无重复元素的无序集合。但是,我无法理解它是如何生成输出的。

例如,考虑以下情况:

>>> x = [1, 1, 2, 2, 2, 2, 2, 3, 3]
>>> set(x)
set([1, 2, 3])

>>> y = [1, 1, 6, 6, 6, 6, 6, 8, 8]
>>> set(y)
set([8, 1, 6])

>>> z = [1, 1, 6, 6, 6, 6, 6, 7, 7]
>>> set(z)
set([1, 6, 7])

set(y) 的输出不应该是:set([1, 6, 8])?我在 Python 2.6 中尝试了以上两个。

【问题讨论】:

  • 你自己说过集合是一个无序集合...

标签: python set


【解决方案1】:

正如你所说,集合是无序的。尽管实现集合的一种方法是使用树,但它们也可以使用哈希表来实现(这意味着按排序顺序获取键可能不是那么简单)。

如果你想对它们进行排序,你可以简单地执行:

sorted(set(y))

这将产生一个包含集合元素的排序列表。 (不是集合。同样,集合是无序的。)

否则,set 唯一保证的是它使元素独一无二(不会出现不止一次)。

希望这会有所帮助!

【讨论】:

  • 注意:集合通常可以使用树来实现。 Python 中的set 不能(有意义地),因为它保证它们要求项目是可散列的并且不要求它们具有可比性。
  • @delnan -- 为了非常清楚,comparable 你的意思是 丰富的比较<, >)。为了使对象成为“可散列的”,它必须实现__eq__
  • @Oliver:非常感谢您的解释。
  • @mgilson:切线,在 2.x 中,如果您覆盖 __eq__ 并且需要在 setdict 键中使用实例,那么您还应该覆盖 __hash__ 这样相等的对象哈希相同。或者定义__hash__ = None 使其不可散列。在 3.x 中,如果您覆盖 __eq__,如果您希望类型是可散列的,则需要覆盖 __hash__
  • @eryksun -- 是的。我想我应该说它必须实现__eq__(除了__hash__)。
【解决方案2】:

作为无序集合类型,set([8, 1, 6]) 等价于set([1, 6, 8])

虽然按排序顺序显示集合内容可能会更好,但这会使repr() 调用更加昂贵。

在内部,set 类型是使用散列表实现的:散列函数用于将项目分成多个桶,以减少检查项目是否是集合的一部分所需的相等操作的数量。

要生成repr() 输出,它只是依次输出每个存储桶中的项目,这不太可能是排序顺序。

【讨论】:

    【解决方案3】:

    正如 +Volatility 和您自己所指出的,集合是无序的。如果您需要按顺序排列元素,只需在现场致电sorted

    >>> y = [1, 1, 6, 6, 6, 6, 6, 8, 8]
    >>> sorted(set(y))
    [1, 6, 8]
    

    【讨论】:

      【解决方案4】:

      在阅读了其他答案后,我仍然无法理解为什么这个集合是无序的。

      向我的伙伴提到这个,他想出了这个比喻:拿弹珠。你把它们放在比大理石宽一点的管子里:你有一个清单。然而,一套是一个袋子。即使你把弹珠一个一个地喂进袋子里;当你把它们从袋子里倒回管子里时,它们的顺序就不同了(因为它们都混在一个袋子里了)。

      【讨论】:

        【解决方案5】:

        Python 的集合(和字典)会以一些的顺序进行迭代和打印,但确切的顺序是任意的,并且不能保证在添加和删除之后保持不变。

        这是一个在添加并删除大量值后设置更改顺序的示例:

        >>> s = set([1,6,8])
        >>> print(s)
        {8, 1, 6}
        >>> s.update(range(10,100000))
        >>> for v in range(10, 100000):
            s.remove(v)
        >>> print(s)
        {1, 6, 8}
        

        这取决于实现,因此您不应依赖它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-09-01
          • 1970-01-01
          • 2020-10-06
          • 2020-10-22
          • 2011-01-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多