Iterting to update nested dictionary fails to save entries

hello,

i am trying to create a nested dictionary via a loop. when i print out each iteration, it works, but when i update the dictionary, only the last items entered are saved.

here is a code example:

from itertools import combinations

test_dict = {'a': [0, 1, 2], 'b': [1, 2, 3, 4, 5, 6], 'c': [0, 1, 2, 3, 4]}

make_combs_dict = {}

for test_name, test_list in test_dict.items():
  #print(test_name, test_list)
  #print()

  group = 0
  for i in range(1, len(test_list) + 1):
    make_combs = list(combinations((test_list), i))

    for comb in make_combs:
      #prints list of combinations for each category
      print(test_name, group, comb) 
      print()

      # saves only the last combination for each category
      make_combs_dict.update({test_name: {group: comb}})

     #also tried:
     #make_combs_dict[test_name].update({group: comb})
     #make_combs_dict[test_name].setDefault(group, []).append(comb)

      print(make_combs_dict)
      print()

      group += 1

where is my error?
thanks in advance.

I’m not entirely sure about your goal here but make sure your keys are unique. Otherwise their value is simply overwritten by the next identical key.

hi. the keys are unique in the final dict:

the final dictionary should have this form:
dictionary → {key 1: {gr 1: combination, gr 2: combination, gr 3: combination}, key 2: {gr 1: combination, gr 2: combination, gr 3: combination}, gr 4: combination}, key 3, etc, etc.}

i don’t mind that the keys are overwritten while the dictionary is being constructed.

my code results in:

{‘a’: {6: (0, 1, 2)}, ‘b’: {62: (1, 2, 3, 4, 5, 6)}, ‘c’: {30: (0, 1, 2, 3, 4)}}, when it should list all the combinations of a (1 → 6), the combinations of b (1 → 62), and the combinations of c (1 → 30).

like this:

comb_dict : {0: (0,), 1: (1,), 2: (2,), 3: (3,), 4: (0, 1), 5: (0, 2), 6: (0, 3), 7: (1, 2), 8: (1, 3), 9: (2, 3), 10: (0, 1, 2), 11: (0, 1, 3), 12: (0, 2, 3), 13: (1, 2, 3), 14: (0, 1, 2, 3)}

i’m not sure why it’s only showing the last combinations. the difference between this result and the result above is that this is not nested by a, b, c, etc. adding the keys in the nested form is what’s breaking the process. this is what i am trying to achieve:

comb_dict : a: {0: (0,), 1: (1,), 2: (2,), 3: (3,), 4: (0, 1), 5: (0, 2), 6: (0, 3), 7: (1, 2), 8: (1, 3), 9: (2, 3), 10: (0, 1, 2), 11: (0, 1, 3), 12: (0, 2, 3), 13: (1, 2, 3), 14: (0, 1, 2, 3)}, b: {0: (0,), 1: (1,), 2: (2,), 3: (3,), 4: (0, 1), 5: (0, 2), 6: (0, 3), 7: (1, 2), 8: (1, 3), 9: (2, 3), 10: (0, 1, 2), 11: (0, 1, 3), 12: (0, 2, 3), 13: (1, 2, 3), 14: (0, 1, 2, 3)}, c: {0: (0,), 1: (1,), 2: (2,), 3: (3,), 4: (0, 1), 5: (0, 2), 6: (0, 3), 7: (1, 2), 8: (1, 3), 9: (2, 3), 10: (0, 1, 2), 11: (0, 1, 3), 12: (0, 2, 3), 13: (1, 2, 3), 14: (0, 1, 2, 3)}

I’d highly suggest getting some print statements into this so you can see how your dictionary is being built at each step (consider breaking out of the loop early or something to limit output).

I still think your issue is going to be from things like this:

make_combs_dict.update({test_name...

Surely test_name remains the same (it only changes in the outer loop). Your output would contains lines like-
make_combs_dict = {'a': {0: (1, 2)}}
but you don’t update the dictionary referenced by key 'a', you overwrite that key-value pair with .update instead.

1 Like

hi, thanks for the input.

i’ve been using print statements throughout my code to check how the dictionary is being built. i have tried to update the library referenced by key, but i don’t understand why i receive a key error for that approach, so i went back to the overwriting approach.

when i use either:

make_combs_dict[test_name].update({group: comb})

or

make_combs_dict[test_name].setDefault(group, []).append(comb)

i get a KeyError: ‘a’

That key access would happen prior to the attribute lookup which would inevitably fail. There’s no dictionary referenced by key 'a' to update at that point.

Consider pre-populating the dictionary with the keys you use, try a defaultdict(dict) or use dict.setdefault (use the key in the method call, not with subscript [key] syntax).

i actually thought of doing that, but thought making an extra list would be inefficient. i’ll take that approach into consideration now that i know it’ll make things simpler. i managed to find a solution by appending the dictionaries twice, updating the list of combinations (the inner dictionary) to another dictionary with the label names.

thanks for your help.

cheers.

1 Like