2

Im trying to create/populate a nested dictionary from a list.

For example, a list [['a','b','c'],value] could create:

data['a']['b']['c'] = value

Giving me a dictionary:

{ 'a': { 'b': { 'c' : value } } }

All help greatly appreciated.

Sirch
  • 407
  • 3
  • 17
  • This seems to be similar: http://stackoverflow.com/questions/24934964/how-to-get-list-of-dict-instead-of-using-collection-defaultdict-in-python – gaw Aug 15 '14 at 12:16
  • This is also close, though a slightly different problem http://stackoverflow.com/questions/14692690/access-python-nested-dictionary-items-via-a-list-of-keys – Cory Kramer Aug 15 '14 at 12:17
  • 1
    Consider using a non-nested dictionary, keyed by tuples. Then you can just do `d = {}; d['a', 'b', 'c'] = value` – Kevin Aug 15 '14 at 12:19

3 Answers3

3

Python:

l = [['a', 'b', 'c'], 'foo']
d = l[1]
for k in l[0][::-1]:
    d = {k : d}
print d

Output:

{'a': {'b': {'c': 'foo'}}}
3

(Assuming that you have more than one of those multi-key/value pairs.)

You can use setdefault to add nested dictionaries for all the sub-key, unless they already exist, each time continuing with that new one for all but the last sub-key. Then put the value into the innermost dict.

def add_nested(d, keys, value):
    for k in keys[:-1]:
        d = d.setdefault(k, {})
    d[keys[-1]] = value

Example:

values = [
    [['a','b','c'], 1],
    [['a','b','d'], 2],
    [['a','e','f'], 3]]

result = {}
for keys, value in values:
    add_nested(result, keys, value)
print(result)

Result:

{'a': {'b': {'c': 1, 'd': 2}, 'e': {'f': 3}}}

Alternatively, you could also use the good old infinite dictionary:

infinidict = lambda: collections.defaultdict(infinidict)
result = infinidict()
for keys, value in values:
    last = reduce(operator.getitem, keys[:-1], result)
    last[keys[-1]] = value
Community
  • 1
  • 1
tobias_k
  • 81,265
  • 12
  • 120
  • 179
0

Use generator and recursive style:

a = [
     [['a','b','c'],1],
     [['c','d'],1],
    ]

def l2d(a):
    def mkd(k,v):
        if not k:
            return v
        return {k[0]:mkd(k[1:],v)}
    for k, v in a:
        yield mkd(k,v)

for d in l2d(a):
    print d

Result:

>>> 
{'a': {'b': {'c': 1}}}
{'c': {'d': 1}}
xiang
  • 393
  • 3
  • 14