Search code examples
pythonloopsdictionarynested

How to change the value of a key in a 2d dictionary while looping


I want to change the value of a key inside a 2D dictionary while looping, but the program is behaving in a way I did not expect.

So first I initiated my 2D dictionary:

dict1 = dict()
dict2 = dict()
list = ['a', 'b', 'c']
list2 = ['A', 'B', 'C']
for i in list2:
    dict1[i] = []
for i in list:
    dict2[i] = dict1

Now I created a nested loop to change the key by appending a value to a list:

count = 0
for i in range(3):
    for j in range(3):
        dict2[list[i]][list2[j]].append(count)
        count += 1
print(dict2)

The outcome is as follows:

{'a': {'A': [0, 3, 6], 'B': [1, 4, 7], 'C': [2, 5, 8]}, 'b': {'A': [0, 3, 6], 'B': [1, 4, 7], 'C': [2, 5, 8]}, 'c': {'A': [0, 3, 6], 'B': [1, 4, 7], 'C': [2, 5, 8]}}

whereas I expected to see this:

{'a': {'A': [0], 'B': [1], 'C': [2]}, 'b': {'A': [3], 'B': [4], 'C': [5]}, 'c': {'A': [6], 'B': [7], 'C': [8]}}

Why is the code behaving in this way and what can I change to get the outcome that I'm looking for?

Thanks!


Solution

  • What @darrylg says in the comment is correct. You can also combine a number of the for-loops you are using, e.g.:

    keys1 = ['a', 'b', 'c']
    keys2 = ['A', 'B', 'C']
    
    dict2 = {k1: {k2: [] for k2 in keys2} for k1 in keys1}
    
    for count, (i, j) in enumerate((i, j) for i in range(3) for j in range(3)):
        dict2[keys1[i]][keys2[j]].append(count)
    

    or, maybe better:

    for count, (k1, k2) in enumerate((k1, k2) for k1 in keys1 for k2 in keys2):
        dict2[k1][k2].append(count)
    

    or perhaps, using itertools.product:

    import itertools
    
    for count, (k1, k2) in enumerate(itertools.product(keys1, keys2)):
        dict2[k1][k2].append(count)
    

    you could write it as a one-liner, although I'd strongly suggest not doing this :-) :

    dict2 = (count := -1) and {k1: {k2: [count := count+1] for k2 in 'ABC'} for k1 in 'abc'}
    

    which given:

    import pprint
    pprint.pprint(dict2)
    

    will print:

    {'a': {'A': [0], 'B': [1], 'C': [2]},
     'b': {'A': [3], 'B': [4], 'C': [5]},
     'c': {'A': [6], 'B': [7], 'C': [8]}}