集合是不是像 python3.6 中的 dicts 一样排序
Posted
技术标签:
【中文标题】集合是不是像 python3.6 中的 dicts 一样排序【英文标题】:Are sets ordered like dicts in python3.6集合是否像 python3.6 中的 dicts 一样排序 【发布时间】:2018-01-16 19:48:23 【问题描述】:由于 Python 3.6 中 dict
实现的更改,现在默认排序。 set
s 现在也保持秩序吗?
我找不到任何关于它的信息,但由于这两种数据结构在它们的底层工作方式上非常相似,我认为可能是这种情况。
我知道dict
s 不会在所有情况下都被订购,但大多数情况下都是如此。如 Python 文档中所述:
这个新实现的顺序保留方面被认为是一个实现细节,不应依赖
【问题讨论】:
@byxor 你不应该依赖随机顺序,集合是任意排序的,但由于散列而不是随机的 如果您对 为什么 集合不按插入顺序感兴趣,请参阅Why don't Python sets preserve insertion order? 【参考方案1】:不,set
s 仍然是无序的。
您可以通过显示一个应该具有“明确定义的哈希顺序”的set
来验证这一点1 以确保我们不会意外得到一个看起来有序但实际上的set
实际上不是:
>>> a_set = 3,2,1
>>> a_set
1, 2, 3
>>> list(a_set)
[1, 2, 3]
如果已订购,您会期望 3, 2, 1
和 [3, 2, 1]
作为示例的结果。
虽然dict
s 实际上是有序的(相同的例子只是稍作修改):
>>> a_dict = 3: 3, 2: 2, 1:1
>>> a_dict
3: 3, 2: 2, 1: 1
>>> list(a_dict)
[3, 2, 1]
1 “定义明确的哈希顺序”:
对于满足0 <= integer < sys.hash_info.modulus
的整数,hash
只是数字本身。这意味着如果集合是根据散列“基于”排序(而不是基于插入“时间”排序)并且散列值不冲突(这就是我使用小数字和仅相差一个的数字的原因)顺序应该是确定性的,因为它们占据了集合中彼此相邻的插槽:
以后者为例:
>>> a_set = 6,7,8,9
>>> a_set
8, 9, 6, 7
【讨论】:
Negativeint
s 也对自己进行哈希处理(-1
除外),尽管我不确定确切的下限是多少
@Chris_Rands 是的,但是因为 -1
和 -2
都哈希到 -2
有一个冲突。:)
是的,-1
这样做是因为它是 C 语言中的错误代码;我相信边界是(sys.maxsize // 4) - 1
,至少这是Martijn Pieters之前告诉我的
很高兴知道。但如果想在hash
期间捕获错误,这是有道理的。我还找到了最大值。这是sys.hash_info.modulus
。 :)【参考方案2】:
set
s 在 Python 3.6 中没有排序,甚至没有作为 CPython 实现细节。一个简单的例子说明了这一点:
>>> import string
>>> string.digits
'0123456789'
>>> set(string.digits)
'7', '0', '2', '8', '6', '9', '1', '5', '4', '3'
Python 3 docs 对此很清楚:
集合是没有重复元素的无序集合。
【讨论】:
但dict
上的文档也说“最好将字典视为 无序 键:值对集,并要求键是唯一的(在一本字典中)。” (source)。这只是语言规范,可以订购实现...
@MSeifert “最好考虑”是我认为的关键措辞,set
文档没有这样的警告
我认为这只是“绒毛”(或包括在内,因为 PyPy 长期以来一直有一个有序的字典)。但是,就像我说的,这只是语言规范。这并不意味着实现可以以有序的方式实现它(即使用存储桶或类似方式)。
评论已过时,现在从文档的该部分中删除了“无序”一词。
我认为在 python 3.6 文档中的措辞保持不变docs.python.org/3.6/tutorial/datastructures.html#dictionaries以上是关于集合是不是像 python3.6 中的 dicts 一样排序的主要内容,如果未能解决你的问题,请参考以下文章