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\$

2 Answers 2

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\$ Commented 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
    Commented 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\$ Commented 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
    Commented May 12, 2015 at 14:58
  • \$\begingroup\$ THNX. Exactly, python 2.7 \$\endgroup\$ Commented May 12, 2015 at 15:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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