I have a string like "food | dairy | milk". The string may consist of more or less words. How do I turn it into a dictionary {'food': {'dairy': {'milk': {'eco': {}}}}}
?
The only way I could achieve it was to create a string and then turn it into a dictionary using exec. I understand it's messy. How could I improve on it?
#!/usr/bin/env python -tt
# -*- coding: utf-8 -*-
# I have a string that represents 'path' to place where new item should be inserted
st="food | dairy | milk"
print st,"< -- string"
keys=st.split(" | ")
print keys,"<-- keys"
new_cat="eco" # should be added
d = {i:{} for i in keys}
print d,"d"
ex_str="{"
for i in keys:
ex_str+="\""+i+"\":{"
ex_str+="\""+str(new_cat)+"\":{}"+"}"*(len(keys)+1)
exec"nd="+ex_str
print nd,"<-- new dict"
2 Answers 2
You use a temporary variable:
st="food | dairy | milk"
keys=st.split(" | ")
new_cat="eco" # should be added
d = t = {} # t is my temporary dictionary
for i in keys:
t[i] = {}
t = t[i]
t[new_cat] = {}
print d
Another way you can do it is going in reverse, like so:
st = "food | dairy | milk"
d = {}
new_cat="eco" # should be added
for key in reversed(st.split(" | ") + [new_cat]):
d = {key: d}
print d
# {'food': {'dairy': {'milk': {'eco': {}}}}}
How this works is it starts with {}
, then it does {the last key: what it is}
({'eco': {}}
), then it does {the second to last key: what it is currently}
({'milk': {'eco': {}}}
), and so on until the end.
But to make it more presentable, you should put it in a function. This also makes it more flexible, and allows it to work for more things.
def str_to_dict(separator, str_, *new_keys):
d = {}
for key in reversed(str_.split(seperator) + new_keys):
d = {key: d}
return d
print str_to_dict(" | ", "food | dairy | milk", "eco")
# {'food': {'dairy': {'milk': {'eco': {}}}}}
print str_to_dict("`", "food`dairy`milk", "eco", ("test",), 5)
# {'food': {'dairy': {'milk': {'eco': {('test',): {5: {}}}}}}}
-
\$\begingroup\$ It looks interesting. Could you explain what does asterisk mean. \$\endgroup\$Sergii Artele– Sergii Artele2015年05月10日 19:56:42 +00:00Commented May 10, 2015 at 19:56
-
\$\begingroup\$ @SergiiArtele The asterisk means that it can take as many arguments as it wants, and all the extra arguments will turn into a tuple called
new_keys
in this case. See stackoverflow.com/questions/36901/… as well. \$\endgroup\$user61114– user611142015年05月10日 19:58:22 +00:00Commented May 10, 2015 at 19:58 -
\$\begingroup\$
for key in reversed(str_.split(separator) + new_keys): TypeError: can only concatenate list (not "tuple") to list
\$\endgroup\$Sergii Artele– Sergii Artele2015年05月12日 11:11:27 +00:00Commented May 12, 2015 at 11:11 -
\$\begingroup\$ @SergiiArtele That seems to be a Python 2 issue. In that case, do
reversed(str_.split(separator) + list(new_keys))
\$\endgroup\$user61114– user611142015年05月12日 14:58:01 +00:00Commented May 12, 2015 at 14:58 -
\$\begingroup\$ THNX. Exactly, python 2.7 \$\endgroup\$Sergii Artele– Sergii Artele2015年05月12日 15:14:27 +00:00Commented May 12, 2015 at 15:14