5
\$\begingroup\$

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"
\$\endgroup\$
3
\$\begingroup\$

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
\$\endgroup\$
2
\$\begingroup\$

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: {}}}}}}}
\$\endgroup\$
5
  • \$\begingroup\$ It looks interesting. Could you explain what does asterisk mean. \$\endgroup\$ May 10 '15 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
    May 10 '15 at 19:58
  • \$\begingroup\$ for key in reversed(str_.split(separator) + new_keys): TypeError: can only concatenate list (not "tuple") to list \$\endgroup\$ May 12 '15 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
    May 12 '15 at 14:58
  • \$\begingroup\$ THNX. Exactly, python 2.7 \$\endgroup\$ May 12 '15 at 15:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.