[英]Sort some list elements in certain positions, leaving other positions unchanged
我有一個元素列表,以及相關的排序鍵
data = [
{'data': 0},
{'key': 'foo', 'data': 1},
{'key': 'bar', 'data': 2},
{'data': 3},
{'key': 'foo', 'data': 4},
{'key': 'bar', 'data': 5},
{'key': 'bar', 'data': 6},
{'data': 7}
]
有些元素有排序key
,有些沒有。 我有一個對一些鍵進行排序的外部表:
ORDER = ['bar', 'foo', 'baz']
預期結果:
[
{'data': 0},
{'key': 'bar', 'data': 2},
{'key': 'bar', 'data': 5},
{'data': 3},
{'key': 'bar', 'data': 6},
{'key': 'foo', 'data': 1},
{'key': 'foo', 'data': 4},
{'data': 7}
]
我需要對數組進行排序,只移動帶有鍵的元素,不移動具有相同鍵的元素。 (基本上,如果鍵比較不需要,我對具有不交換元素的元素有部分順序)。 據我所知,現有的list.sort
/ sorted
(在 Python 中)不支持這種類型的排序。
我強烈懷疑這個問題已經解決了很多次,但我找不到合適的名稱來搜索。
這種類型的排序如何被調用?
創建排序記錄的迭代器:
it1 = iter(sorted((d for d in data if 'key' in d),
key=lambda d_: ORDER.index(d_['key'])))
接下來,編寫一個列表推導式以選擇性地用“key”覆蓋記錄,而其他記錄保持不變。
res = [d if 'key' not in d else next(it1) for d in data]
print (res)
# [{'data': 0},
# {'key': 'bar', 'data': 2},
# {'key': 'bar', 'data': 5},
# {'data': 3},
# {'key': 'bar', 'data': 6},
# {'key': 'foo', 'data': 1},
# {'key': 'foo', 'data': 4},
# {'data': 7}]
幾點:
可能值得將ORDER
轉換為將鍵映射到位置的字典,因此查找是恆定的時間。 這應該會降低排序步驟的復雜性。
sorted
返回一個列表,然后將其轉換為迭代器,因此無法避免中間列表。
如果您的鍵很少,您可以在 O(n) 時間內執行此操作,例如使用桶排序之類的東西:
import pprint
from collections import defaultdict
from itertools import chain
# create buckets
buckets, no_key = defaultdict(list), {}
for i, d in enumerate(data):
if 'key' in d:
buckets[d['key']].append(d)
else:
no_key[i] = d
# create one sorted list for elements with keys, basically iterate over the buckets in ORDER
chained = list(chain.from_iterable([buckets[key] for key in ORDER]))[::-1]
# combine the two iterables, chained and no_key into the final result
final = [no_key.pop(i) if i in no_key else chained.pop() for i in range(len(data))]
pprint.pprint(final)
Output
[{'data': 0},
{'data': 2, 'key': 'bar'},
{'data': 5, 'key': 'bar'},
{'data': 3},
{'data': 6, 'key': 'bar'},
{'data': 1, 'key': 'foo'},
{'data': 4, 'key': 'foo'},
{'data': 7}]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.