Given the list below, using Python 3 how can I generate a nested dictionary with list[0] having list[1:] as nested children.
list = [
["Layer 1.A", "Layer 1.B"],
["layer 2.A", "Layer 2.B"],
["Layer 3"],
["Layer 4"]
]
I have already tried a multitude of things, but none have given me the correct output. I have tried the following already:
- tried using python's product (generated all permutations, but did not give correct output. It look like:
[
["Layer 1.A", "Layer 2.A", "Layer 3", "Layer 4"],
["Layer 1.A", "Layer 2.B", "Layer 3", "Layer 4"],
["Layer 1.B", "Layer 2.A", "Layer 3", "Layer 4"],
["Layer 1.B", "Layer 2.B", "Layer 3", "Layer 4"]
]
- tried creating a nested dictionary using nested for loops (couldn't figure out how to append to dictionary)
- Tried using recursion (trying
dict(zip(keys, dictionary) for keys in product(*dictionary2))
, dict or zip iterated trough each element of each string) - tried using a lambda function
Output desired: Please note how only the first layer changes, and the guts are the same.
[
{"Layer 1.A":
{
"Layer 2.A":
{
"Layer 3" : "Layer 4"
},
"Layer 2.B":
{
"Layer 3" : "Layer 4"
}
}
},
{"Layer 1.B":
{
"Layer 2.A":
{
"Layer 3" : "Layer 4"
},
"Layer 2.B":
{
"Layer 3" : "Layer 4"
}
}
}
]
CodePudding user response:
You generated all the permutations. Now create your nested dictionary from those permutations. To do this, we can define a function that will take the original dictionary, a list of keys, and the value to set at that nested key. If a key doesn't exist, it is created and its value is set to a new dictionary
def nested_set(obj, keys, value):
for key in keys[:-1]:
try:
# Drill down until the penultimate key
obj = obj[key]
except KeyError:
obj[key] = {}
obj = obj[key]
# Set value of last key
obj[keys[-1]] = value
For example, doing nested_set(my_dict, ['a', 'b', 'c'], 'd')
on an empty my_dict = dict()
gives the result:
{'a': {'b': {'c': 'd'}}}
Knowing this, you can use your list of permutations like so:
perms = [
["Layer 1.A", "Layer 2.A", "Layer 3", "Layer 4"],
["Layer 1.A", "Layer 2.B", "Layer 3", "Layer 4"],
["Layer 1.B", "Layer 2.A", "Layer 3", "Layer 4"],
["Layer 1.B", "Layer 2.B", "Layer 3", "Layer 4"]
]
my_dict = dict()
for p in perms:
nested_set(my_dict, p[:-1], p[-1])
which gives almost the result you want:
{
'Layer 1.A': {
'Layer 2.A': {
'Layer 3': 'Layer 4'
},
'Layer 2.B': {
'Layer 3': 'Layer 4'
}
},
'Layer 1.B': {
'Layer 2.A': {
'Layer 3': 'Layer 4'
},
'Layer 2.B': {
'Layer 3': 'Layer 4'
}
}
}
Converting this to the desired list is easy:
result = [{k: v} for k, v in my_dict.items()]
which gives:
[
{
'Layer 1.A': {
'Layer 2.A': {
'Layer 3': 'Layer 4'
},
'Layer 2.B': {
'Layer 3': 'Layer 4'
}
}
},
{
'Layer 1.B': {
'Layer 2.A': {
'Layer 3': 'Layer 4'
},
'Layer 2.B': {
'Layer 3': 'Layer 4'
}
}
}
]
CodePudding user response:
This feels like a natural problem for a recursive solution.
def Cartesian(theList):
if len(theList) == 2:
result = [ [x,y] for x in theList[0] for y in theList[1] ]
return result
else:
result = [[x,y] for x in theList[0] for y in Cartesian(theList[1:])]
return result
This implementation will return a list with the nested structure that you are seeking. I don't really know much about formatting the result as JSON.