Python3 中 set 进行列表去重时为什么会自动排序(升序)?

In [35]: set([1, 3, 8, -2, 99, 98, 77, 1, 5, 3, 77, 12])
Out[35]: {-2, 1, 3, 5, 8, 12, 77, 98, 99}


In [31]: o = [2,5,1,2,4,6,0,33,5.4,6.4]

In [32]: c = set(o)

In [33]: c
Out[33]: {0, 1, 2, 4, 5, 5.4, 6, 6.4, 33}
Python3 中 set 进行列表去重时为什么会自动排序(升序)?

4 回复

楼主多试一试几次

即使你看到了十次都是有序的,也不要相信,set 是无序的 set 是无序的 set 是无序的


你遇到的情况不是 set 在去重时“自动排序”,而是它在内部实现上使用了哈希表(hash table),并且整数类型(int)的哈希值就是其本身。当你将列表转换为集合时,元素的存储顺序由它们的哈希值、哈希冲突解决策略以及当前哈希表的大小共同决定。对于连续的小整数,这种机制常常会让它们在迭代时看起来像是按升序排列了,但这只是一个巧合,并不是集合的保证行为。

看看这个例子就明白了:

# 连续小整数,看起来“有序”
list1 = [3, 1, 4, 1, 5, 9, 2, 6, 5]
print(set(list1))  # 可能输出 {1, 2, 3, 4, 5, 6, 9}

# 负数或大整数,顺序就“乱”了
list2 = [30, 10, -5, 10, 20, -5]
print(set(list2))  # 可能输出 {10, 20, 30, -5}

# 字符串更明显,完全不是插入顺序
list3 = ['banana', 'apple', 'cherry', 'apple']
print(set(list3))  # 可能输出 {'cherry', 'banana', 'apple'}

关键点:

  1. set无序集合,Python 官方文档明确说明它“不记录元素插入顺序”。
  2. 你看到的“升序”只是特定数据(如小整数)在特定 CPython 实现下的表象,不能依赖这个特性。
  3. 如果你需要去重且保留原列表的插入顺序,应该用 dict.fromkeys() 方法(Python 3.6+ 字典保持插入顺序):
    my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5]
    unique_ordered = list(dict.fromkeys(my_list))
    print(unique_ordered)  # 输出 [3, 1, 4, 5, 9, 2, 6]
    

总结:别把 set 的迭代顺序当回事,要保序就用 dict.fromkeys()。

楼主多看文档

5.4. Sets

Python also includes a data type for sets. A set is an unordered collection with no duplicate elements. Basic uses include membership testing and eliminating duplicate entries. Set objects also support mathematical operations like union, intersection, difference, and symmetric difference.

Curly braces or the set() function can be used to create sets. Note: to create an empty set you have to use set(), not {}; the latter creates an empty dictionary, a data structure that we discuss in the next section.

从文档能看出啥?无序的?

回到顶部