3

Not sure how to use a tuple as a set of strings the way I would like.

I would like my json to look like:

'item': {
  'a': {
    'b': {
      'c': 'somevalue'
    }
  }
}

Which could be done with:

item = {}
item['a']['b']['c'] = "somevalue"

However a, b, and c are dynamic, so I understand I need to use a tuple, but this does not do what I would like:

item = {}
path = ('a','b','c')
item[path] = "somevalue"
json.dump(item, sys.stdout)

So I am getting the error:

TypeError("key " + repr(key) + " is not a string"

How do I dynamically get item['a']['b']['c']?

martineau
  • 119,623
  • 25
  • 170
  • 301
  • Have you tried writing a recursive function that does your insertion? – YSelf Apr 16 '18 at 21:53
  • Just put the three values in variables, and use those to do the **indexing** (which is what is really going on with in statements like `item['a']['b']['c']`). – martineau Apr 16 '18 at 21:54
  • What do you mean by dynamic? – Anton vBR Apr 16 '18 at 21:57
  • Have a look at: https://stackoverflow.com/questions/19189274/defaultdict-of-defaultdict-nested?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa – Anton vBR Apr 16 '18 at 22:05
  • Hi, I see you're new to SO. If you feel an answer solved the problem, please [mark it as 'accepted’](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235) by clicking the green check mark. This helps keep the focus on older SO which still don't have answers. – fferri May 01 '18 at 18:31

2 Answers2

0

AFAIK there are no builtins for this task, so you need to write a couple of recursive functions:

def xset(dct, path, val):
    if len(path) == 1:
        dct[path[0]] = val
    else:
        if path[0] not in dct: dct[path[0]] = {}
        xset(dct[path[0]], path[1:], val)

def xget(dct, path):
    if len(path) == 1:
        return dct[path[0]]
    else:
        return xget(dct[path[0]], path[1:])

Usage:

>>> d = {}
>>> xset(d, ('a', 'b', 'c'), 6)
>>> d
{'a': {'b': {'c': 6}}}
>>> xset(d, ('a', 'b', 'd', 'e'), 12)
>>> d
{'a': {'b': {'c': 6, 'd': {'e': 12}}}}
>>> xget(d, ('a', 'b', 'c'))
6
fferri
  • 18,285
  • 5
  • 46
  • 95
0

Try this:

item = {}

for i in reversed(path):  
    tmp = {**item}
    item ={}
    item[i] = {**tmp} if path.index(i)!=len(path)-1 else 'somevalue'
Mehrdad Pedramfar
  • 10,941
  • 4
  • 38
  • 59