簡體   English   中英

使用同一字典中的鍵擴展 dict 值

[英]Expanding dict value using keys in the same dictionary

我嘗試使用同一字典中的鍵來擴展字典的值。 換句話說,我嘗試用另一個/可能擴展的集合替換dic值(現有集合)。 當值包含字典中的鍵時,就會發生擴展。

輸入:

dic = {
    '10': {'01', '02'},
    '11': {'03', '04'},
    '20': {'05', '10'},
    '21': {'06', '11'},
    '30': {'07', '20'},
    '40': {'08', '21', '30'},
    '50': {'09', '40'}
}

預期輸出:

{
    '10': {'01', '02'},
    '11': {'03', '04'},
    '20': {'05', '01', '02'},
    '21': {'06', '03', '04'},
    '30': {'07', '05', '01', '02'},
    '40': {'08', '06', '03', '04', '07', '05', '01', '02'},
    '50': {'09', '08', '06', '03', '04', '07', '05', '01', '02'}
}

我試圖創建一個遞歸函數......

def transform_dic(d):
    def func(k):
        v = d.get(k, k)
        if v != k:
            for e in v:
                v = func(v)
        return v
    d2 = {}
    for k, v in d.items():
        d2[k] = {func(i) for i in v}
    return d2

print(transform_dic(dic))

TypeError:不可散列的類型:'set'

您要遞歸擴展的內容是 dict 中的集合,而不是 dict 本身。 你總是只有一個字典。

出於這個原因,我相信寫一個遞歸函數來擴展一個集合,然后使用這個函數來擴展字典會更容易。

def expanded_dict(d):
    return {k: expanded_set(v, d) for k,v in d.items()}

def expanded_set(s, d):
    return {
        y
        for x in s
            for y in (expanded_set(d[x], d) if x in d
                      else (x,))
    }

請注意, expanded_set返回一個新集,而不修改輸入集或輸入字典; 並且expanded_dict返回一個新的字典而不修改輸入字典。

明確您的函數是返回新對象還是修改輸入對象是一種很好的做法。 例如, sorted返回一個新列表而不修改其輸入,而list.sort修改一個列表而不返回任何內容。

這是一個通過修改字典來擴展字典而不返回任何內容的函數:

def expand_dict(d):
    stable = False
    while not stable:
        stable = True
        for k in d:
            for x in list(d[k]):
                if x in d:
                    d[k].remove(x)
                    d[k].update(d[x])
                    stable = False

用你的例子測試:

dic = {
    '10': {'01', '02'},
    '11': {'03', '04'},
    '20': {'05', '10'},
    '21': {'06', '11'},
    '30': {'07', '20'},
    '40': {'08', '21', '30'},
    '50': {'09', '40'}
}

print(expanded_dict(dic))
# {'10': {'01', '02'}, '11': {'03', '04'}, '20': {'01', '05', '02'}, '21': {'03', '06', '04'}, '30': {'07', '01', '02', '05'}, '40': {'04', '06', '08', '05', '02', '01', '07', '03'}, '50': {'04', '06', '08', '02', '05', '01', '07', '09', '03'}}

print(dic)
# {'10': {'01', '02'}, '11': {'03', '04'}, '20': {'10', '05'}, '21': {'11', '06'}, '30': {'07', '20'}, '40': {'08', '30', '21'}, '50': {'40', '09'}}

expand_dict(dic)
# no return value

print(dic)
# {'10': {'01', '02'}, '11': {'03', '04'}, '20': {'01', '02', '05'}, '21': {'03', '06', '04'}, '30': {'01', '05', '07', '02'}, '40': {'04', '06', '08', '05', '02', '01', '07', '03'}, '50': {'04', '06', '08', '05', '02', '01', '07', '09', '03'}}

您可以迭代輸出字典並檢查集合內的值是否是結果字典的成員:

from typing import Dict, Set


dic = {
    '10': {'01', '02'},
    '11': {'03', '04'},
    '20': {'05', '10'},
    '21': {'06', '11'},
    '30': {'07', '20'},
    '40': {'08', '21', '30'},
    '50': {'09', '40'}
}

output = {
    '10': {'01', '02'},
    '11': {'03', '04'},
    '20': {'05', '01', '02'},
    '21': {'06', '03', '04'},
    '30': {'07', '05', '01', '02'},
    '40': {'08', '06', '03', '04', '07', '05', '01', '02'},
    '50': {'09', '08', '06', '03', '04', '07', '05', '01', '02'}
}

def conv(d: Dict[str, set[str]]) -> Dict[str, set[str]]:        
    result: Dict[str, set[str]] = {}
    for k,vs in d.items():
        result[k] = set()
        for v in vs:
            if v in result:
                for t in result[v]:
                    result[k].add(t)
            else:
                result[k].add(v)
    return result

print(conv(dic))
print(conv(dic)==output)

輸出將是

{'10': {'02', '01'}, '11': {'03', '04'}, '20': {'02', '05', '01'}, '21': {'06', '03', '04'}, '30': {'02', '05', '07', '01'}, '40': {'05', '03', '02', '01', '06', '07', '08', '04'}, '50': {'05', '03', '09', '02', '01', '06', '07', '08', '04'}}
True

它必須是遞歸的嗎?

def transform_dic(d):
    for k, v in d.items():
        for n in set(v):
            if n in d:
                d[k].remove(n)
                d[k].update(d[n])

transform_dic(dic)
print(dic)

如果您不想修改原始字典,請使用deepcopy

def transform_dic(d):
    d = deepcopy(d)
    for k, v in d.items():
        for n in set(v):
            if n in d:
                d[k].remove(n)
                d[k].update(d[n])
    return d

print(transform_dic(dic))

輸出:

{
    '10': {'01', '02'},
    '11': {'03', '04'},
    '20': {'01', '05', '02'},
    '21': {'03', '04', '06'},
    '30': {'01', '07', '05', '02'},
    '40': {'01', '08', '07', '04', '06', '03', '05', '02'},
    '50': {'01', '08', '07', '04', '06', '03', '05', '02', '09'}
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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