Python 字典(dict)本身是無序的(Python 3.7+ 保持插入順序,但非排序順序)。常見需求包括:依鍵排序、依值排序、取得排序後的鍵值對列表、保持字典順序等。本文系統整理四種主流排序方法、效能比較、進階技巧與最佳實務。
sorted() 回傳新列表,不修改原字典list.sort() 原地排序列表
d = {'b': 2, 'a': 1, 'c': 3}
# 依鍵排序(預設)
sorted_items = sorted(d.items())
print(sorted_items) # [('a', 1), ('b', 2), ('c', 3)]
# 依鍵降序
sorted_items_desc = sorted(d.items(), reverse=True)
print(sorted_items_desc) # [('c', 3), ('b', 2), ('a', 1)]
# 明確指定 key(相同效果)
sorted_items = sorted(d.items(), key=lambda x: x[0])
d = {'b': 2, 'a': 1, 'c': 3}
# 兩種寫法等價
keys = sorted(d.keys())
keys = sorted(d) # 直接迭代字典得到鍵
print(keys) # ['a', 'b', 'c']
# 取得對應值列表
values = [d[k] for k in keys]
print(values) # [1, 2, 3]
# 或用 map(較舊風格)
values = list(map(d.get, keys))
d = {'b': 2, 'a': 1, 'c': 3}
values = sorted(d.values())
print(values) # [1, 2, 3]
# 依值降序
values_desc = sorted(d.values(), reverse=True)
print(values_desc) # [3, 2, 1]
d = {'b': 2, 'a': 1, 'c': 3, 'd': 2}
# 依值升序
by_value = sorted(d.items(), key=lambda x: x[1])
print(by_value) # [('a', 1), ('b', 2), ('d', 2), ('c', 3)]
# 依值降序
by_value_desc = sorted(d.items(), key=lambda x: x[1], reverse=True)
print(by_value_desc) # [('c', 3), ('b', 2), ('d', 2), ('a', 1)]
# 依值排序,值相同再依鍵排序(穩定排序)
by_value_then_key = sorted(d.items(), key=lambda x: (x[1], x[0]))
print(by_value_then_key) # [('a', 1), ('b', 2), ('d', 2), ('c', 3)]
d = {'apple': 3, 'banana': 2, 'cherry': 3, 'date': 1}
# 依值降序,值同則依鍵升序
result = sorted(d.items(), key=lambda x: (-x[1], x[0]))
print(result) # [('apple', 3), ('cherry', 3), ('banana', 2), ('date', 1)]
d = {'a': -5, 'bb': 3, 'ccc': -2, 'dddd': 4}
# 依值絕對值排序
by_abs = sorted(d.items(), key=lambda x: abs(x[1]))
print(by_abs) # [('bb', 3), ('ccc', -2), ('a', -5), ('dddd', 4)]
# 依鍵長度排序
by_key_len = sorted(d.items(), key=lambda x: len(x[0]))
print(by_key_len) # [('a', -5), ('bb', 3), ('ccc', -2), ('dddd', 4)]
from collections import OrderedDict
d = {'b': 2, 'a': 1, 'c': 3}
# Python 3.7+:dict 保持插入順序
sorted_dict = dict(sorted(d.items()))
print(sorted_dict) # {'a': 1, 'b': 2, 'c': 3}
# Python 3.6 或需明確語意:
sorted_od = OrderedDict(sorted(d.items()))
| 方法 | 程式碼 | 時間複雜度 | 適用場景 |
|---|---|---|---|
| 1. items()+sort | items = d.items(); items.sort() | O(n log n) | 需 (k,v) 列表、原地修改可接受 |
| 2. keys()+sort | keys = d.keys(); keys.sort(); [d[k] for k in keys] | O(n log n) | 只需鍵列表、後續查值 |
| 3. keys()+map | keys = d.keys(); keys.sort(); map(d.get, keys) | O(n log n) | 函式式風格、Python 2 較快 |
| 4. sorted(items, key=...) | sorted(d.items(), key=lambda x: x[1]) | O(n log n) | 依值排序、需保留鍵、最通用 |
實測差異微小(微秒級),建議優先考慮可讀性與功能需求:依值排序用方法四,依鍵排序用 sorted(d.items()) 最直觀。
import heapq
d = {f'key{i}': i for i in range(1000000)}
# 只取最大 10 筆,O(n log k) 優於 O(n log n)
top10 = heapq.nlargest(10, d.items(), key=lambda x: x[1])
print(top10)
class SortedDictCache:
def __init__(self, data):
self._data = data
self._sorted_cache = None
self._dirty = True
def get_sorted(self, key_func=None, reverse=False):
if self._dirty:
self._sorted_cache = sorted(self._data.items(), key=key_func, reverse=reverse)
self._dirty = False
return self._sorted_cache
def update(self, new_data):
self._data.update(new_data)
self._dirty = True
# 陷阱 1:以為 dict 會自動排序
d = {'c': 3, 'a': 1, 'b': 2}
# Python 3.7+ 印出順序 = 插入順序,非排序順序
print(d) # {'c': 3, 'a': 1, 'b': 2}
# 陷阱 2:sorted 回傳列表,非字典
result = sorted(d.items())
print(type(result)) #
# 需要字典用 dict(result)
# 陷阱 3:值相同順序不穩定(Python 排序是穩定的,但依值排序時鍵順序不保證)
d = {'b': 1, 'a': 1}
print(sorted(d.items(), key=lambda x: x[1])) # 可能 [('b',1),('a',1)] 或 [('a',1),('b',1)]
# 解決:key=lambda x: (x[1], x[0]) 明確指定次序
Python 字典排序核心在於 sorted() 搭配 key 參數:
sorted(d.items()) 或 sorted(d)sorted(d.items(), key=lambda x: x[1])key=lambda x: (x[1], x[0]) 或 key=lambda x: (-x[1], x[0])dict(sorted(...)) (3.7+) 或 OrderedDictheapq.nlargest/nsmallest理解字典無序本質、排序回傳列表、lambda key 靈活指定排序依據,能靈活應對各類排序需求。