Dasith
Dasith

Reputation: 363

Dynamically creating a dictionary in python

I want to dynamically build a dictionary based on the string.

I have 5 strings:

ABC
ABC BCD DEF
ABC BCD FGH
ABC BCD FGH IJK
ABC DEF GHI

I want to create this into a dict:

dict = {
 "ABC" : {
   "BCD": {"DEF": {}, "FGH":{IJK}},
   "DEF": {"GHI"},
  }
}

This is what I have tried so far, but I'm not sure how to create the new key if there is a key error.

# orgs = list of string from about
for org in orgs:
    org_path_sp = org .strip().split()   
    org_cur = org_dict
    for org_el in org_path_sp:
        try:
            org_cur = org_cur[org_el.strip()]

        except KeyError:
            pass
            # create the new entry

Upvotes: 4

Views: 3784

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476574

You are on the right track. What you should do is each time construct an empty dictionary in case the key is missing:

org_dict = {}

for org in orgs.split('\n'):
    org_path_sp = org .strip().split()   
    org_cur = org_dict
    for org_el in org_path_sp:
        org_el = org_el.strip()
        if org_el not in org_cur:
            org_cur[org_el] = org_cur = {}
        else:
            org_cur = org_cur[org_el]

Or we can alter your code a bit:

org_dict = {}

for org in orgs.split('\n'):
    org_path_sp = org .strip().split()   
    org_cur = org_dict
    for org_el in org_path_sp:
        org_el = org_el.strip()
        try:
            org_cur = org_cur[org_el]
        except KeyError:
            org_cur[org_el] = org_cur = {}

For example:

>>> orgs = '''ABC
... ABC BCD DEF
... ABC BCD FGH
... ABC BCD FGH IJK
... ABC DEF GHI'''
>>> org_dict = {}
>>> 
>>> for org in orgs.split('\n'):
...     org_path_sp = org .strip().split()   
...     org_cur = org_dict
...     for org_el in org_path_sp:
...         org_el = org_el.strip()
...         if org_el not in org_cur:
...             org_cur[org_el] = org_cur = {}
...         else:
...             org_cur = org_cur[org_el]
... 
>>> org_dict
{'ABC': {'BCD': {'DEF': {}, 'FGH': {'IJK': {}}}, 'DEF': {'GHI': {}}}}

Here the inner elements are not sets, but dicts. It would make more sense to use dictionaries here, since if you later want to update your elements and add extra orgs, then we can easily run thins program again over a partially filled dictionary.

Note that dictionaries are unoredered. There is thus no guarantee about the order of the keys in the result. You can use an OrderedDict if that is necessary. For example:

from collections import OrderedDict

org_dict = OrderedDict()

for org in orgs.split('\n'):
    org_path_sp = org .strip().split()   
    org_cur = org_dict
    for org_el in org_path_sp:
        org_el = org_el.strip()
        if org_el not in org_cur:
            org_cur[org_el] = org_cur = OrderedDict()
        else:
            org_cur = org_cur[org_el]

This would then result in:

>>> pprint(org_dict)
OrderedDict([('ABC',
              OrderedDict([('BCD',
                            OrderedDict([('DEF', OrderedDict()),
                                         ('FGH',
                                          OrderedDict([('IJK',
                                                        OrderedDict())]))])),
                           ('DEF', OrderedDict([('GHI', OrderedDict())]))]))])

We can convert these back into dictionaries, but then the order will again be lost.

Upvotes: 3

Related Questions