1

I want to delete all dictionaries that have 'original_y' key. But no matter what I do, I can only delete the first item. Below is the code

list1 = [{'original_x': 70, 'original_y': 134, 'original_count': 1},{'original_x': 78, 'original_y': 134, 'original_count': 2}, \
{'matched_x': 73, 'matched_y': 130, 'matched_pixel_count': 3}, {'matched_x': 73, 'matched_y': 130, 'matched_pixel_count': 3}, {'matched_x': 71, 'matched_y': 132, 'matched_pixel_count': 1}, \
{'matched_x': 76, 'matched_y': 132, 'matched_pixel_count': 2}, {'matched_x': 71, 'matched_y': 132, 'matched_pixel_count': 1}, {'matched_x': 76, 'matched_y': 132, 'matched_pixel_count': 2}, \
{'matched_x': 71, 'matched_y': 133, 'matched_pixel_count': 1}, {'matched_x': 78, 'matched_y': 133, 'matched_pixel_count': 1}, {'matched_x': 71, 'matched_y': 133, 'matched_pixel_count': 1}]

list1_copy = list1.copy()
index = 0
delete_list = []
for each_dict in list1:
   if 'original_y' in each_dict:
      print(" index is " + str(index) + " " + str(list1[index]) )
      delete_list.append(index)
      
   index += 1

print(list1[1])      

list1.pop(0)
list1.pop(1) 

print(list1)

Help would be appreciated.

M K
  • 55
  • 7
  • How about `no_ys = [d for d in list1 if 'original_y' not in d]`? – josemz Nov 13 '21 at 01:33
  • 1
    because deleting an element from a list moves all the indices after it generally you want to iterate over a copy of the list backwards so that when you specify an index of the original it is still valid, otherwise create a copy with all the element you want to keep (which is usually easier) – Tadhg McDonald-Jensen Nov 13 '21 at 01:35
  • 1
    so when you `pop` the first element, the second one that should be removed is now at a different index so the second `pop` removes the wrong one, try `print`ing the result of the `pop` to check. – Tadhg McDonald-Jensen Nov 13 '21 at 01:36
  • FYI: use `enumerate(list1)` to iterate over both indexes and values in a list. – Barmar Nov 13 '21 at 01:38
  • Why are you specifically popping `0` and `1`. What is `delete_list` for? – Barmar Nov 13 '21 at 01:39

4 Answers4

2

I figured out. When I delete the first item, the index value gets updated, so the second index value changes as result.

So I need to update each time an item gets deleted.

The below code works.

list1 = [{'original_x': 70, 'original_y': 134, 'original_count': 1}, \
{'original_x': 78, 'original_y': 134, 'original_count': 2}, {'matched_x': 73, 'matched_y': 130, 'matched_pixel_count': 3}, \
 {'matched_x': 73, 'matched_y': 130, 'matched_pixel_count': 3}, \
{'original_x': 78, 'original_y': 134, 'original_count': 2}, {'matched_x': 71, 'matched_y': 132, 'matched_pixel_count': 1}, \
 {'original_x': 78, 'original_y': 134, 'original_count': 2}]


index = 0
index_list = []
for each_dict in list1:
   if 'original_y' in each_dict:
      index_list.append(index)
      

   index += 1
   

delete = 0
for index in index_list:
   list1.pop(index - delete)
   delete += 1
   
   
print(list1)
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
M K
  • 55
  • 7
1

It appears that your not deleting the elements that contain the original_y key. Try adding list.pop(index) after delete_list.append(index) in your for loop.

JustMakeStuff
  • 419
  • 3
  • 19
  • 3
    This won't work: See https://stackoverflow.com/questions/6260089/strange-result-when-removing-item-from-a-list-while-iterating-over-it – Barmar Nov 13 '21 at 01:41
0

Why not just make an empty list and add all the dicts that don't contain 'original_y'?

new_list = []

for each_dict in list1:
    if 'original_y' not in each_dict:
        new_list.append(each_dict)

list1 = new_list # then have list1 point to the new list
AJ Biffl
  • 493
  • 3
  • 10
-1

try popping in reverse order:

for idx in reversed(delete_list):
    list1.pop(idx)

If you pop early indices it shifts all the other elements which invalidates the rest of the indices, if you pop them in the reverse order each removal doesn't mess up the rest of the indices to remove.

>>> x = ["BAD", 1,2,3, "BAD", 5,6]
>>> [idx for idx,elem in enumerate(x) if elem=="BAD"]
[0, 4]
>>> x.pop(0)
'BAD'
>>> x.pop(4) # is no longer the same BAD element
5
>>> x = ["BAD", 1,2,3, "BAD", 5,6]
>>> x.pop(4) # if we remove the second bad one first 
'BAD'
>>> x.pop(0) # then earlier index isn't shifted.
'BAD'
Tadhg McDonald-Jensen
  • 20,699
  • 5
  • 35
  • 59