【发布时间】:2015-09-13 09:23:16
【问题描述】:
sorted()documentation(强调我的):
内置的 sorted() 函数保证稳定。一种是 如果保证不改变元素的相对顺序,则稳定 比较相等 [...]
在下面的代码中,键 8 和 16 具有相同的值,即它们将通过 key=lambda x: d[x] 进行比较:
d = {8: 0, 16: 0, 'a': 1}
for i in range(200):
print(sorted(d, key=lambda x: d[x]))
# Prints always the same
# [8, 16, 'a']
# [8, 16, 'a']
# [8, 16, 'a']
# ......
现在让我们尝试对字典进行小修改:
示例 1:
for i in range(10):
if i == 5:
del d[8]
del d[16]
d.update({16: 0})
d.update({8: 0})
print(sorted(d, key=lambda x: d[x]))
# Prints:
# [8, 16, 'a']
# [8, 16, 'a']
# [8, 16, 'a']
# [8, 16, 'a']
# [8, 16, 'a']
# [16, 8, 'a'] <----- it changed the order
# [16, 8, 'a']
# [16, 8, 'a']
# [16, 8, 'a']
# [16, 8, 'a']
id(d) 保持不变。内容也保持不变。改变的是密钥插入的顺序。
注意:
选择这些键是为了使它们导致hash collisions:
是8个占位还是16个由哪个决定 先到派对
示例 2:
d = {8: 0, 16: 0, 'a': 1}
c = {16: 0, 8: 0, 'a': 1}
print(sorted(d, key=lambda x: d[x]))
print(sorted(c, key=lambda x: d[x]))
我知道d 和c 在这里是不同的对象:
id(d) # 140067442777736
id(c) # 140067442811016
但我希望sorted() 以完全相同的方式处理d == c 的对象。
示例 3: 一个不同的例子如下:
d = {'a': 0, 'b': 0, 'c': 0, 'd': 1}
print(sorted(d, key=lambda x: d[x]))
在多个不同的运行中运行它(不是带有for循环)每次都会给出不同的顺序。
注意:假设您使用 Python 3.3 or higher 和您的 PYTHONHASHSEED=random
问题:
订单不稳定:
- 对于获得其顺序的同一对象 已修改(示例 1)。
- 对于比较相等的 2 个对象(示例 2)。
- 对于完全相同的代码的不同运行(示例 3)。
上面提到的订单不稳定是错误还是我遗漏了什么?我是否期望所有 3 个示例都有一个稳定的顺序,从而误解了文档?
【问题讨论】:
-
是什么让您认为 sorted 有问题?键的顺序发生了变化。
sorted()保持你给它的相对顺序。给它[16, 8]不同于给它[8, 16]。 -
@MartijnPieters 它的文档让我觉得在不同的运行中,它会给出相同的结果。它没有。是的,
[16,8] != [8,16]。 但是{16,8} == {8,16}. -
所以?仅仅因为字典相等并不意味着 sorted 可以看到或关心。它以给定的顺序被赋予一系列键。你改变了这个顺序。
-
但您根本没有根据
16或8进行排序。您正在根据字典中的相应值进行排序。如果值是相同的排序将使用最先出现的元素。试试像 -sorted([3,4,5,1,2],key=lambda x:1)这样的东西,你真的希望 sorted 改变顺序吗? -
不是
sorted()改变了顺序,sorted()是从字典本身获取改变的顺序。
标签: python sorting python-3.4