Home > Software design >  traversal of every branch of a dictionary of dictionaries till the last value using a python recursi
traversal of every branch of a dictionary of dictionaries till the last value using a python recursi

Time:11-02

Hi I have a complex dictionary of dictionaries:

dict1 = {
    "CurrentSet": "/Sets/4332FF55-0430-456D-8DA5-55DDC3698723",
    "Model": "MacBookPro11,2",
    "NetworkServices": {
        "36135701-9BA6-4005-F25A-BF75E9627244": {
            "DNS": {},
            "IPv4": {"ConfigMethod": "DHCP"},
            "IPv6": {"ConfigMethod": "Automatic"},
            "Interface": {
                "DeviceName": "en0",
                "Hardware": "Ethernet",
                "Type": "Ethernet",
                "UserDefinedName": "Ethernet",
            },
            "Proxies": {"ExceptionsList": ["*.local", "169.254/16"], "FTPPassive": 1},
            "SMB": {},
            "UserDefinedName": "Ethernet",
        }
    },
    "Sets": {
        "4332FF55-0430-456D-8DA5-55DDC3698723": {
            "Network": {
                "Global": {
                    "IPv4": {"ServiceOrder": ["36135701-9BA6-4005-F25A-BF75E9627244"]}
                },
                "Service": {
                    "36135701-9BA6-4005-F25A-BF75E9627244": {
                        "__LINK__": "/NetworkServices/36135701-9BA6-4005-F25A-BF75E9627244"
                    }
                },
            },
            "UserDefinedName": "Automatic",
        }
    },
    "System": {
        "Network": {"HostNames": {"LocalHostName": "Tacos-MacBook-Pro"}},
        "System": {
            "ComputerName": "Taco’s MacBook Pro",
            "ComputerNameEncoding": 0,
        },
    },
    "__VERSION__": 20191120,
}

I am trying to write a python recursive function, to flatten each branch to its last string/or numeric/or list value.

So the desired output is :

CurrentSet|/Sets/F554332F-0430-456D-8DA5-55DDC3698723
Model|MacBookPro11,2
NetworkServices|35701361-F25A-4005-9BA6-BF75E9627244|DNS|
NetworkServices|35701361-F25A-4005-9BA6-BF75E9627244|IPv4|ConfigMethod|DHCP
NetworkServices|35701361-F25A-4005-9BA6-BF75E9627244|IPv6|ConfigMethod|Automatic
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|DeviceName|en0
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|Hardware|Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|Type|Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|UserDefinedName|Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Proxies|ExceptionsList|['*.local', '169.254/16']
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Proxies|FTPPassive|1
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|SMB|
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|UserDefinedName|Ethernet
Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Global|IPv4|ServiceOrder|['36135701-9BA6-4005-F25A-BF75E9627244']
Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Service|36135701-9BA6-4005-F25A-BF75E9627244|__LINK__|/NetworkServices/36135701-9BA6-4005-F25A-BF75E9627244
Sets|4332FF55-0430-456D-8DA5-55DDC3698723|UserDefinedName|Automatic
System|Network|HostNames|LocalHostName|Tacos-MacBook-Pro
System|System|ComputerName|Taco’s MacBook Pro
System|System|ComputerNameEncoding|0
__VERSION__|20191120

Actual Output that I'm getting:

CurrentSet|/Sets/4332FF55-0430-456D-8DA5-55DDC3698723
Model|MacBookPro11,2
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|DNS|{}
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|ConfigMethod|DHCP
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|ConfigMethod|Automatic
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|DeviceName|en0
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Hardware|Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Type|Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|UserDefinedName|Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Proxies|ExceptionsList|['*.local', '169.254/16']
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Proxies|FTPPassive|1
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Proxies|SMB|{}
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Proxies|UserDefinedName|Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Proxies|Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Global|IPv4|ServiceOrder|['36135701-9BA6-4005-F25A-BF75E9627244']
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Proxies|Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Global|IPv4|Service|36135701-9BA6-4005-F25A-BF75E9627244|__LINK__|/NetworkServices/36135701-9BA6-4005-F25A-BF75E9627244
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Proxies|Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Global|IPv4|Service|36135701-9BA6-4005-F25A-BF75E9627244|UserDefinedName|Automatic
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Proxies|Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Global|IPv4|Service|36135701-9BA6-4005-F25A-BF75E9627244|System|Network|HostNames|LocalHostName|Tacos-MacBook-Pro
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Proxies|Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Global|IPv4|Service|36135701-9BA6-4005-F25A-BF75E9627244|System|Network|HostNames|System|ComputerName|Taco’s MacBook Pro
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Proxies|Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Global|IPv4|Service|36135701-9BA6-4005-F25A-BF75E9627244|System|Network|HostNames|System|ComputerNameEncoding|0
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|IPv6|Interface|Proxies|Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Global|IPv4|Service|36135701-9BA6-4005-F25A-BF75E9627244|System|Network|HostNames|System|__VERSION__|20191120

My code is:

def parse_dict(dict1, key_lst):
    for key, val in dict1.items():
        key_lst.append(key)
        if isinstance(val, dict) and len(val) > 0:
            parse_dict(val, key_lst)
        else:
            print('|'.join(map(str, key_lst))   '|'   str(val))
            key_lst.pop() # <-- Does this line need changes ?

key_lst = []
parse_dict(dict1, key_lst)

What am I doing wrong ? Please help

CodePudding user response:

Maybe something like this. walk() is a recursive generator function that yields 2-tuples of "key trails" and their related values. Dicts, lists and tuples are iterated into; everything else is considered a leaf value.

def walk(item, trail=()):
    if isinstance(item, (list, tuple)):
        item = enumerate(item)
    elif isinstance(item, dict):
        item = item.items()
    else:
        raise TypeError(f"unsupported type")

    for key, value in item:
        new_trail = trail   (key,)
        if isinstance(value, (dict, list, tuple)):
            yield from walk(value, new_trail)
        else:
            yield (new_trail, value)


for key, value in walk(dict1):
    print("|".join(str(x) for x in key), value)

For your data, it prints out

CurrentSet /Sets/4332FF55-0430-456D-8DA5-55DDC3698723
Model MacBookPro11,2
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|ConfigMethod DHCP
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv6|ConfigMethod Automatic
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|DeviceName en0
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|Hardware Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|Type Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|UserDefinedName Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Proxies|ExceptionsList|0 *.local
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Proxies|ExceptionsList|1 169.254/16
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Proxies|FTPPassive 1
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|UserDefinedName Ethernet
Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Global|IPv4|ServiceOrder|0 36135701-9BA6-4005-F25A-BF75E9627244
Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Service|36135701-9BA6-4005-F25A-BF75E9627244|__LINK__ /NetworkServices/36135701-9BA6-4005-F25A-BF75E9627244
Sets|4332FF55-0430-456D-8DA5-55DDC3698723|UserDefinedName Automatic
System|Network|HostNames|LocalHostName Tacos-MacBook-Pro
System|System|ComputerName Taco�s MacBook Pro
System|System|ComputerNameEncoding 0
__VERSION__ 20191120

CodePudding user response:

Building on @AKX's approach and being more specific to this particular question's demands:

def walk(obj, trail=""):
    if isinstance(obj, dict):
        for key, value in obj.items():
            yield from walk(value, f"{trail}|{key}")
    else:
        yield f"{trail}|{obj}".lstrip("|")

for line in walk(dict1):
    print(line)

CurrentSet|/Sets/4332FF55-0430-456D-8DA5-55DDC3698723
Model|MacBookPro11,2
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv4|ConfigMethod|DHCP
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|IPv6|ConfigMethod|Automatic
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|DeviceName|en0
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|Hardware|Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|Type|Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Interface|UserDefinedName|Ethernet
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Proxies|ExceptionsList|['*.local', '169.254/16']
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|Proxies|FTPPassive|1
NetworkServices|36135701-9BA6-4005-F25A-BF75E9627244|UserDefinedName|Ethernet
Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Global|IPv4|ServiceOrder|['36135701-9BA6-4005-F25A-BF75E9627244']
Sets|4332FF55-0430-456D-8DA5-55DDC3698723|Network|Service|36135701-9BA6-4005-F25A-BF75E9627244|__LINK__|/NetworkServices/36135701-9BA6-4005-F25A-BF75E9627244
Sets|4332FF55-0430-456D-8DA5-55DDC3698723|UserDefinedName|Automatic
System|Network|HostNames|LocalHostName|Tacos-MacBook-Pro
System|System|ComputerName|Taco’s MacBook Pro
System|System|ComputerNameEncoding|0
__VERSION__|20191120
  • Related