Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Iterating over nested dictionary returns only first element

I have this nested dictionary ("dictionary of dictionaries")

source = {
    "OuterVal0": {"InnerVal": [10, 21, 96],"InnerVal2": [100, 91, 71]},
    "OuterVal1": {"InnerVal": [21, 19, 76],"InnerVal2": [1, 1, 1]},
    "OuterVal2": {"InnerVal": [1, 1, 96],"InnerVal2": [10, 9, 7]},
    "OuterVal3": {"InnerVal": [0, 2, 6],"InnerVal2": [1, 911, 718]},
    "OuterVal4": {"InnerVal": [12, 13, 9],"InnerVal2": [1000, 910, 701]},
    "OuterVal5": {"InnerVal": [110, 211, 961],"InnerVal2": [10, 911, 918]},     
}

And I want to create a new one which would consist of outer keys associated with inner values (see expected output below)
I use this recursive function:

def myPrint(d, key=""):
    output = {}
    for k, v in d.items():
        i = 0
        if isinstance(v, dict):
          return  myPrint(v, k)
        else:
            for  value in d.values():
                newkey = (f"{i}_{key}")
                output[newkey] = value
                i += 1
    return output

But when I try to print that:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

print(myPrint(source))

I get this (only the first dictionary is processed:

# {'0_OuterVal0': [10, 21, 96], '1_OuterVal0': [100, 91, 71]}

But I would like to have something like this (all dictionaries processed)

"""
Expected output
{'0_OuterVal0': [10, 21, 96], '1_OuterVal0': [100, 91, 71]}
{'0_OuterVal1':[21, 19, 76], '1_OuterVal1': [1, 1, 1]}
.
.
.
{'0_OuterVal5':  [110, 211, 961], '1_OuterVal5': [10, 911, 918]}

"""

What am I doing wrong?

Thank you very much in advance for any help.

>Solution :

The problem is that when you call return myPrint(v, k) for the first time you compute the values for the first dictionary and then return instead of continuing to the other values in the for loop.

Changing the function to:

def myPrint(d, key=""):
    output = {}
    for k, v in d.items():
        i = 0
        if isinstance(v, dict):
          output.update(myPrint(v, k))
        else:
            for  value in d.values():
                newkey = (f"{i}_{key}")
                output[newkey] = value
                i += 1
    return output

will return a big dictionary, for you example:

{'0_OuterVal0': [10, 21, 96], '1_OuterVal0': [100, 91, 71],
 '0_OuterVal1': [21, 19, 76], '1_OuterVal1': [1, 1, 1],
 '0_OuterVal2': [1, 1, 96], '1_OuterVal2': [10, 9, 7],
 '0_OuterVal3': [0, 2, 6], '1_OuterVal3': [1, 911, 718],
 '0_OuterVal4': [12, 13, 9], '1_OuterVal4': [1000, 910, 701],
 '0_OuterVal5': [110, 211, 961], '1_OuterVal5': [10, 911, 918]}

However, the function can be nicely packed in a non-recursive way as follow:

output = [{f'{ii}_{k}': vv  for (k, v) in source.items() for ii, (kk, vv) in enumerate(v.items())}]
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading