Reputation: 363
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
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 set
s, but dict
s. 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