簡體   English   中英

如何將此扁平字典轉換為嵌套字典?

[英]how to transfer this flat dict to a nested dict?

有一個簡單的字典,像這樣:

{"a.b": "foo", "a.c": "bar", "d.e.f":"baz"}

以及如何使用Python將dict轉移到此:

{
    "a": 
        {
            "b": "foo",
            "c": "bar"
        },
    "d": 
        {
            "e":
                {
                    "f": "baz"
                }
        }
}

您可以在上split. 到最后一個值以及之前的所有內容:

*parents, key =  k.split('.')

您可以使用類似以下內容的內容來挖掘嵌套字典(如有必要,可以創建它們):

end = reduce(lambda x, y: x.setdefault(y, {}) , parents, new_d) 

在這里end將是鏈末尾的字典。 因此,此時您只需分配值即可。 就像是:

from functools import reduce

d = {"a.b": "foo", "a.c": "bar", "d.e.f":"baz", "d.e.g":"M", 'l':"single_key_test" }

new_d = {}

for k in d:
    *parents, key =  k.split('.')
    end = reduce(lambda x, y: x.setdefault(y, {}) , parents, new_d)
    end[key] = d[k]

print(new_d)

結果:

{'a': {'b': 'foo', 'c': 'bar'}, 'd': {'e': {'f': 'baz', 'g': 'M'}}, 'l': 'single_key_test'}

首先,您必須將鍵分割為'.' 獲得路徑。

然后,您可以創建一個從一個路徑創建嵌套字典的函數:

def make_nested_dict(iterable, final):
    """Make nested dict from iterable"""
    if iterable:
        head, *tail = iterable
        return {head: make_nested_dict(tail, final)}
    else:
        return final

其工作原理如下:

d = {"a.b": "foo", "a.c": "bar", "d.e.f":"baz"}    

for key in d:
    paths = key.split('.')
    nested_path = make_nested_dict(paths, d[key])
    print(nested_path)

並給出以下路徑:

{'a': {'b': 'foo'}}
{'a': {'c': 'bar'}}
{'d': {'e': {'f': 'baz'}}}

然后,您可以創建一個將兩個嵌套字典遞歸合並的函數:

def merge_nested_dicts(d1, d2):
    """Merge two nested dictionaries together"""
    for key in d2:
        if key in d1:
            if isinstance(d2[key], dict) and isinstance(d1[key], dict):
                merge_nested_dicts(d1[key], d2[key])
        else:
            d1[key] = d2[key]

    return d1

您可以通過更新結果嵌套的dict進行合並:

nested_dict = {}

for key in d:
    paths = key.split('.')
    nested_path = make_nested_dict(paths, d[key])
    nested_dict = merge_nested_dicts(nested_dict, nested_path)

print(nested_dict)

現在,這給出了以下內容:

{'a': {'b': 'foo', 'c': 'bar'}, 'd': {'e': {'f': 'baz'}}}

帶有一些注釋的完整代碼:

def make_nested_dict(iterable, final):
    """Make nested dictionary path with a final attribute"""

    # If iterable, keep recursing
    if iterable:

        # Unpack key and rest of dict
        head, *tail = iterable

        # Return new dictionary, recursing on tail value
        return {head: make_nested_dict(tail, final)}

    # Otherwise assign final attribute
    else:
        return final

def merge_nested_dicts(d1, d2):
    """Merge two nested dictionaries together"""

    for key in d2:

        # If we have matching keys
        if key in d1:

            # Only merge if both values are dictionaries
            if isinstance(d2[key], dict) and isinstance(d1[key], dict):
                merge_nested_dicts(d1[key], d2[key])

        # Otherwise assign normally
        else:
            d1[key] = d2[key]

    return d1

if __name__ == "__main__":
    d = {"a.b": "foo", "a.c": "bar", "d.e.f":"baz", "d.e.g":"M", 'l':"single_key_test" }  

    nested_dict = {}

    for key in d:

        # Create path
        paths = key.split('.')

        # Create nested path
        nested_path = make_nested_dict(paths, d[key])

        # Update result dict by merging with new dict
        nested_dict = merge_nested_dicts(nested_dict, nested_path)

    print(nested_dict)

暫無
暫無

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

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