I want to convert a list of lists to multi-level nested dictionaries like so:
x = [[1, 2, 3, 4],
[1, 2, 4, 5],
[5, 6, 7, 8]]
print(f(x))
## {
## 1: {2: {3: 4},
## {4: 5}},
## 5: {6: {7: 8}}
## }
The list inside can be arbitrary long. Any ideas would be very helpful. For any set of nested keys, there is only one unique value possible. Thank you. So, the list mentioned below does not occur:
x = [[1,2,3,4],
[1,2,3,5]]
I tried the function below but it throws an AttributeError: ‘int’ object has no attribute ‘keys’.
Also, it updates incorrectly as mentioned below, so not very helpful.
def listoflists_dict(listformat):
a = dict()
cur = a
for inner_list in listformat:
for i, ele in enumerate(inner_list):
print(a)
if (ele not in cur.keys()) and (i < len(inner_list) - 1):
cur[ele] = dict()
cur = cur[ele]
elif (ele not in cur.keys()) and (i == len(inner_list) - 1):
cur[ele] = inner_list[-1]
else:
cur = cur[ele]
return a
listformat = [[1, 2, 3, 4],
[1, 2, 4, 5],
[5, 6, 7, 8]]
listoflists_dict(listformat)
## {}
## {1: {}}
## {1: {2: {}}}
## {1: {2: {3: {}}}}
## {1: {2: {3: {4: 4}}}}
## {1: {2: {3: {4: 4, 1: {}}}}}
## {1: {2: {3: {4: 4, 1: {2: {}}}}}}
## {1: {2: {3: {4: 4, 1: {2: {4: {}}}}}}}
## {1: {2: {3: {4: 4, 1: {2: {4: {5: 5}}}}}}}
## {1: {2: {3: {4: 4, 1: {2: {4: {5: 5}}}}}}}
>Solution :
Good idea, with two major problems:
- You don’t reset
cur
for eachele
. Movingcur = a
one line down will fix this problem. - The element that needs special handling is
len(inner_list) - 2
, notlen(inner_list) - 1
. You must not processlen(inner_list) - 1
, so abreak
is useful.
With this, your code becomes:
def listoflists_dict(listformat):
a = dict()
for inner_list in listformat:
cur = a
for i, ele in enumerate(inner_list):
if (ele not in cur.keys()) and (i < len(inner_list) - 2):
cur[ele] = dict()
cur = cur[ele]
elif (ele not in cur.keys()) and (i == len(inner_list) - 2):
cur[ele] = inner_list[-1]
break
else:
cur = cur[ele]
return a
Now, several non-essential comments:
ele not in cur.keys()
will sequentially test each key incur
, sincecur.keys()
is a generator;ele not in cur
will directly test if a key is present in a dict, and should therefore be preferred- Similarly,
{}
, as a literal is faster thandict()
, which must invoke a function - It is easier to tear off the last two elements, rather than having to check for them
With that, here is a faster and sleeker version:
def listoflists_dict(listformat):
a = {}
for *path, key, val in listformat:
cur = a
for ele in path:
if ele not in cur:
cur[ele] = {}
cur = cur[ele]
cur[key] = val
return a