[英]How to rearrange an Ordered Dictionary with a based on part of the key from a list
我正在根據列表中的鍵重新排列一些有序詞典。 如:
old_OD = OrderedDict([('cat_1',1),
('dog_1',2),
('cat_2',3),
('fish_1',4),
('dog_2',5)])
現在,我有了該組的訂單清單。
order = ['dog', 'cat', 'fish']
然后將字典中的項目組合在一起,得到結果,如下所示:
new_OD = OrderedDict([('dog_1',2),
('dog_2',5),
('cat_1',1),
('cat_2',3),
('fish_1',4)])
我找到了一個很好的相關問題: 如何基於列表和重新排序OrderedDict 對OD進行 重新排序 ,我將在第二個鏈接中使用解決方案
new_od = OrderedDict([(k, None) for k in order if k in old_od])
new_od.update(old_od)
現在,在我的情況下,“ k”不是new_od的完全匹配項和所需的鍵值,我應該如何修改以構造新的od?
編輯:那么,如果沒有下划線標記關鍵字的位置,例如我們有“ Big_cat_3”或“ dog_black_2”,該怎么辦? 關鍵字可以在字符串中的任何位置。 將密鑰分組在一起后,就不需要字母數字順序了。
在這里,我分享了兩種解決方案。
1.對於具有相同前綴的鍵, 請保持初始OrderedDict
的順序
在這里,我使用列表 OrderDict
來迭代order
列表和OrderDict
。 基於比較,我們傳遞具有所需順序的元組列表以創建OrderedDict
對象:
>>> from collections import OrderedDict
>>> old_OD = OrderedDict([('cat_1',1),
... ('dog_1',2),
... ('cat_2',3),
... ('fish_1',4),
... ('dog_2',5)])
>>> order = ['dog', 'cat', 'fish']
>>> new_OD = OrderedDict([(k,v) for o in order for k, v in old_OD.items() if k.startswith(o+'_')])
# to match the prefix pattern of <key> + "_" ^
new_OD
將保存在哪里:
OrderedDict([('dog_1', 2), ('dog_2', 5), ('cat_1', 1), ('cat_2', 3), ('fish_1', 4)])
2.對於具有相同前綴的鍵, 對元素進行按字典順序排序
我們可以使用帶有嵌套列表 itertools.chain
sorted
和itertools.chain
修改上述解決方案,以實現以下目的:
>>> from itertools import chain
>>> new_OD = OrderedDict(chain(*[sorted([(k,v) for k, v in old_OD.items() if k.startswith(o+'_')]) for o in order]))
new_OD
將保存在哪里:
OrderedDict([('dog_1', 2), ('dog_2', 5), ('cat_1', 1), ('cat_2', 3), ('fish_1', 4)])
你可以建立在每個項目對應一個字典order
,以它的索引,然后使用sorted
函數,在每個按鍵的子映射按鍵功能old_OD
出現在映射字典的鍵對應的指數使用映射字典:
keys = {k: i for i, k in enumerate(order)}
OrderedDict(sorted(old_OD.items(), key=lambda t: keys.get(next(i for i in t[0].split('_') if i in keys))))
返回:
OrderedDict([('dog_1', 2), ('dog_2', 5), ('cat_1', 1), ('cat_2', 3), ('fish_1', 4)])
您可以將函數groupby()
與已排序的字典一起使用:
from collections import OrderedDict
from itertools import groupby, chain
from operator import itemgetter
ld_OD = OrderedDict([('cat_1',1),
('dog_1',2),
('cat_2',3),
('fish_1',4),
('dog_2',5)])
order = ['dog', 'cat', 'fish']
gb = groupby(sorted(ld_OD.items()), key=lambda t: t[0].split('_')[0])
gb = {k: list(g) for k, g in gb}
OrderedDict(chain.from_iterable(itemgetter(*order)(gb)))
# OrderedDict([('dog_1', 2), ('dog_2', 5), ('cat_1', 1), ('cat_2', 3), ('fish_1', 4)])
解決O(n)時間復雜度(而不是帶排序的O(n log n))時 ,解決此問題的更有效方法是構建一個字典,該字典映射按order
出現的每個鍵的子字符串(應該轉換)用於有效查找一組),以自屬於鍵-值對的列表old_OD
,然后生成新的OrderedDict
由通過一系列的長度的迭代的索引order
,並輸出到OrderedDict
在映射字典的值鍵控構造通過索引處的order
值:
keys = set(order)
mapping = {}
for k, v in old_OD.items():
mapping.setdefault(next(i for i in k.split('_') if i in keys), []).append((k, v))
OrderedDict(t for i in range(len(order)) for t in mapping[order[i]])
返回:
OrderedDict([('dog_1', 2), ('dog_2', 5), ('cat_1', 1), ('cat_2', 3), ('fish_1', 4)])
這是使用regex
和partial
函數的另一種方法。
import re
from operator import itemgetter
from functools import partial
first = itemgetter(0)
pattern = '|'.join(order) # 'dog|cat|fish'
def group(order, pattern, txt):
item = first(txt)
res = re.search(pattern, item)
return order.index(res.group(0))
p = partial(group, order, pattern)
OrderedDict(sorted(old_OD.items(), key=p))
OrderedDict([('dog_1', 2),
('dog_2', 5),
('cat_1', 1),
('cat_2', 3),
('fish_1', 4)])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.