0

I have a dictionary in python which looks like this

my_dict = {
    '100':[['a', [10], [5]]],
    '101':[['a', [10], [7]]],
    '102':[['a', [10], [11]]],
    '103':[['a', [10], [4]]], 
}

To create my_dict,

my_dict = dict()
id_nums = ['100', '101', '102', '103', ...]
for id in id_nums:
   info_list = list()
   ## code to populate info list
   # based on certain conditions
   if some_condition:
       info_list.insert(0, 'a')
       info_list.insert(1, list1) # list_1 is passsed from another function
   else:
       info_list.insert(0, 'a')
       info_list.insert(1, [])
   if other_condition:
       info_list.insert(2, list2) # list2 is being passed from other function
   else:
       info_list.insert(2, [])
   if id not in my_dict.keys():
       my_dict[id] = list()
   my_dict[id].append(info_list)

Where info list contains ['a', [10], [x].

I'm looping over all the keys in the dict and my goal is to delete number at 1st index in each value i.e. 10. To achieve this I have:

for k in my_dict.keys():
    my_dict[k][1].remove(10)

When I execute above code, at the very first key i.e. '100' the remove method also deletes 10 from the values of all the keys in my_dict.

Can anybody help me understand why this happens? and also how it can be avoided?

Thanks

Vishal
  • 21
  • 4
  • 2
    It does no such thing. If I just do `my_dict['100'][1].remove(10)` it only removes the 10 from the entry under `'100'`. Obviously if you loop through all the keys it will do the same thing for all the other keys as well, but it won't remove all of them on the first iteration. – Samwise Sep 06 '22 at 16:41
  • 6
    Show how you created the dictionary. I suspect the nested `[10]` lists are all references to the same list. – Barmar Sep 06 '22 at 16:42
  • Related: https://stackoverflow.com/questions/240178/list-of-lists-changes-reflected-across-sublists-unexpectedly – Barmar Sep 06 '22 at 16:42
  • 1
    @MechanicPig That edit may not be valid. You removed a `[`, when OP **may have** a extra `]` at the end. Edits should not correct errors in the code. – TheMaster Sep 06 '22 at 16:44
  • @TheMaster In fact, each value is missing a `]`, and if they are really missing, the resulting error will be that the index is out of range. – Mechanic Pig Sep 06 '22 at 16:45
  • 1
    @MechanicPig Yes. That should be addressed in the answer or edited by OP himself – TheMaster Sep 06 '22 at 16:46
  • I agree with @TheMaster since the code is written by Vishal and he should be the one to fix the code. Though I suspect he has an issue with the logic. – thethiny Sep 06 '22 at 16:47
  • my bad for the missing ']'. I have edited the question. @Barmar your suspicion is correct. the nested [] inside each value all reference to same list. I'm using my_dict[key] = list() to create the list holding each nested-lists. In my knowledge using list() should create a new object every time. am I right in saying this? – Vishal Sep 06 '22 at 17:02
  • 1
    I'm talking about how you're creating the `[10]` lists that are nested at the next level. Edit the question to show how you're creating the whole thing. – Barmar Sep 06 '22 at 17:08
  • Your editing is still incomplete, and you have avoided the key point: the creation process of `info_list`. – Mechanic Pig Sep 06 '22 at 17:32
  • @MechanicPig I have edited the code, I hope now it includes all necessary details. – Vishal Sep 06 '22 at 17:44
  • @Vishal Very well, this editing revealed the error. You didn't copy `list1` and `list2` when you built `info_list`, but simply put their references into it, which made the same list in multiple positions in the dictionary. I think the answer section already has the answer you need. – Mechanic Pig Sep 06 '22 at 17:50
  • @MechanicPig you are right. Not copying list1 and list2 were the problem. info_list.insert(0, Using deepcopy(list1)) solves the issue. Returning to python has been not easy as I thought. – Vishal Sep 06 '22 at 17:55
  • I want to thank everyone for their help. you guys are awesome – Vishal Sep 06 '22 at 17:56

2 Answers2

1

Your question is a good example of why you need to show us actual code, rather than sterilized and re-typed code. My bet is that what you actually wrote is more like this:

lst = [10]
my_dict = {
    '100':['a', lst, [5]],
    '101':['a', lst, [7]],
    '102':['a', lst, [11],
    '103':['a', lst, [4]], 
}

In that case, if you did my_dict['100'][1].remove(10), that WOULD affect all of the keys in your dictionary, because you don't have four separate lists. You have four references to the SAME list. Changing that list changes all the views of that list.

Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
  • *Your question is a good example of why you need to show us actual code, rather than sterilized and re-typed code* It's a good example of why OP should produce reproducible code as written in [mcve]. I don't think we should encourage original code dump in SO. The only problem was the sterilized retyped code wasn't reproducible. – TheMaster Sep 07 '22 at 08:08
0

I am not sure about what you are looking for but I will give you several scenarios on how to delete objects from your dictionary

scenario 1

To delete the value in index 1 from the first key (in this case key='100') in the dictionary

my_dict = {
    '100':[['a'], [10], [5]],
    '101':[['a'], [10], [7]],
    '102':[['a'], [10], [11]],
    '103':[['a'], [10], [4]], 
}
k = list(my_dict.keys())[0]
del my_dict[k][1]
print(my_dict)

output

{'100': [['a'], [5]], '101': [['a'], [10], [7]], '102': [['a'], [10], [11]], '103': [['a'], [10], [4]]}

scenario 2

To delete the value in index 0 for the list in index 1 from the first key in the dictionary.

my_dict = {
    '100':[['a'], [10], [5]],
    '101':[['a'], [10], [7]],
    '102':[['a'], [10], [11]],
    '103':[['a'], [10], [4]], 
}
k = list(my_dict.keys())[0]
del my_dict[k][1][0]
print(my_dict)

output

{'100': [['a'], [], [5]], '101': [['a'], [10], [7]], '102': [['a'], [10], [11]], '103': [['a'], [10], [4]]}

scenario 3

To delete the values in index 1 for all keys in the dictionary.

my_dict = {
    '100':[['a'], [10], [5]],
    '101':[['a'], [10], [7]],
    '102':[['a'], [10], [11]],
    '103':[['a'], [10], [4]], 
}
for k in my_dict:
    del my_dict[k][1]

print(my_dict)

output

{'100': [['a'], [5]], '101': [['a'], [7]], '102': [['a'], [11]], '103': [['a'], [4]]}

scenario 4

To delete the first value in the index 1 for all keys in the dictionary.

my_dict = {
    '100':[['a'], [10], [5]],
    '101':[['a'], [10], [7]],
    '102':[['a'], [10], [11]],
    '103':[['a'], [10], [4]], 
}
for k in my_dict:
    del my_dict[k][1][0]
print(my_dict)

output

{'100': [['a'], [], [5]], '101': [['a'], [], [7]], '102': [['a'], [], [11]], '103': [['a'], [], [4]]}