0

EDIT:

I forgot to mention that there are other dictionaries and lists, and the solutions suggested so far work very well for my example, but not if I want to add more dictionaries using different paths/lists.

For example:

d1 = {"firstKey":"Value_1"}
d2 = {"secondKey":"Value_2"}
d3 = {"thirdKey":"Value_3"}

p1 = ["level_1a", "level_1b", "level_1c"]
p2 = ["level_1a", "level_1d", "level_1e"]
p2 = ["level_2a", "level_2b"]

I would need to add/merge all 3 dictionaries d1, d2, d3 (and more eventually) in the same "master" dictionary, nested under all keys listed in p1, p2 and p3. Note that if a key is shared (for example "level_1a"), the existing key needs to be used, not creating a new one.

The final dictionary obtained from the three lists (and more eventually, this is just an example) should look like this:

{
    "level_1a":{
        "level_1b":{"level_1c":{"firstKey":"Value_1"}},
        "level_1d":{"level_1e":{"secondKey":"Value_2"}}
    },
    "level_2a":
        {"level_2b":{"thirdKey":"Value_3"}}
}

ORIGINAL POST:

I have a simple dictionary that I need to nest deep inside another dictionary, and the keys are stored in a list (in reversed order).

My basic dictionary looks like this: {"firstKey":"Value_1"}

The list of keys looks like this: ["level_1a", "level_1b", "level_1c"]

This is the results that I'm trying to produce:

{
 "level_1a":{
        "level_1b":{
               "level_1c":
                          {"firstKey":"Value_1"}
                   }
            }
}

This is the code that I tried, it seems like my loop keeps on adding elements instead of replacing them...

masterDict = {}

d1 = {"firstKey":"Value_1"}
p1 = ["level_1a", "level_1b", "level_1c"]
tempDict = d1.copy()

for level in reversed(p1):
    print(level)
    tempDict[level] = tempDict
    print(f'TempDict = {tempDict}')
    print('-=-=-=-')

This is what my code outputs:

level_1c
TempDict = {'firstKey': 'Value_1', 'level_1c': {...}}
-=-=-=-
level_1b
TempDict = {'firstKey': 'Value_1', 'level_1c': {...}, 'level_1b': {...}}
-=-=-=-
level_1a
TempDict = {'firstKey': 'Value_1', 'level_1c': {...}, 'level_1b': {...}, 'level_1a': {...}}
-=-=-=-

Is there a way to nest that simple dictionary only one time, using the keys in the list (and the previous dictionary becomes the new value for the keys)?

Thanks very much in advance!

2
  • is there any other dictionary or lists? could you include a bit more sample? Commented Apr 20, 2022 at 16:59
  • @enke, Yes, there are other dictionaries and lists, and the solutions suggested so far work very well for my example, but not if I want to add more dictionaries using different paths/lists. For example: ` d1 = {"firstKey":"Value_1"} d2 = {"secondKey":"Value_2"} d3 = {"thirdKey":"Value_3"} p1 = ["level_1a", "level_1b", "level_1c"] p2 = ["level_1a", "level_1d", "level_1e"] p2 = ["level_2a", "level_2b"] ` I would need to add all 3 dictionaries d1, d2, d3 in the same "master" dictionary, nested under all keys listed in p1, p2 and p3. Commented Apr 20, 2022 at 18:36

2 Answers 2

1

One option is to use dict.setdefault recursively:

def build_nested(ps, ds, d_out={}):

    def nested(p, d_in, d_out):
        if len(p)==1:
            d_out[p[0]] = d_in
        else:
            nested(p[1:], d_in, d_out.setdefault(p[0], {}))

    for p, d in zip(ps, ds):
        nested(p, d, d_out)
       
    return d_out

tmp = build_nested([p1,p3], [d1,d3])
out = build_nested([p2],[d2], tmp)

Output:

{'level_1a': {'level_1b': {'level_1c': {'firstKey': 'Value_1'}},
  'level_1d': {'level_1e': {'secondKey': 'Value_2'}}},
 'level_2a': {'level_2b': {'thirdKey': 'Value_3'}}}
Sign up to request clarification or add additional context in comments.

5 Comments

Hello @enke, Thanks for your reply. It works for this case, but I forgot to include important information. Please see the edit in my post. Thanks!
@Famp I edited the answer. It should work for the general case now.
Thanks, @enke! Will this work if I need to update the dictionary "on the fly" while I loop an XML structure? What I mean is that I will have to update the dictionary "n" times with one dictionary and one list, not update it one time with "n" dictionaries and "n" lists. Sorry if I didn't explain well, this is not easy for me to explain... :-(
@Famp edited. Now it should work on the fly as well. Just make sure to pass in lists as arguments; see the arguments passed into the function to get out.
Thanks again, @enke! This works as expected, and it's working too for what I need to do. I just need to pass lists for the two first arguments as you said, and pass the previous dictionary (the one to update) as third argument. I'll have to study your answer because I'm not understanding everything right away, but I'm sure that I can manage to understand if I put in a bit of efforts... :-) Have a great day and thanks again!
0

This can be done using a placeholder variable and a loop. Then just updating the placeholder with the dict:

current = master_dict = {}
data = {"firstKey":"Value_1"}
keys = ["level_1a", "level_1b", "level_1c"]

for key in keys:
    current[key] = current = {}
current.update(data)

>>> master_dict
{'level_1a': {'level_1b': {'level_1c': {'firstKey': 'Value_1'}}}}

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.