簡體   English   中英

如何根據列表中的部分鍵重新排列有序詞典

[英]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 sorteditertools.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)])

這是使用regexpartial函數的另一種方法。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM