Skip to content
Advertisement

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:

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.

Advertisement

Answer

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())}]
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement