Home > database >  I am not getting the right output for dictionary and list in python
I am not getting the right output for dictionary and list in python

Time:06-13

roll_number = [47, 64, 69, 37, 76, 83, 95, 97]
sample_dict = {'Jhon':47, 'Emma':69, 'Kelly':76, 'Jason':97}
 
for a in roll_number:
    if a not in sample_dict.values():
        roll_number.remove(a)

print(roll_number)

My output is [47, 69, 76, 95, 97] instead of [47, 69, 76, 97]. Can someone please explain?

CodePudding user response:

The issue I see is that you're iterating over the array while removing items from it. That leads to unsafe removal.

You could use a set to 'freeze' the array and remove its values safely:

roll_number = [47, 64, 69, 37, 76, 83, 95, 97]
sample_dict = {'Jhon':47, 'Emma':69, 'Kelly':76, 'Jason':97}

roll_set = set(roll_number)
for a in roll_number:
    if a not in sample_dict.values():
        roll_set.remove(a)

print(roll_set)

It'll print {97, 69, 76, 47}. If you want a list you can use list(roll_set).

Althoug set is a standard python type, you could also use another temporary list and would have the same result.

CodePudding user response:

You are removing elements while iterating the list. (Bad Idea) Removing elements while iterating the list will affect the iterator.

As mentioned here, there are several approaches:

  • use a list comprehension to create a new list containing only the elements you don't want to remove
  • create a copy of the original list
  • by assigning to the slice somelist[:], you can mutate the existing list to contain only the items you want
  • use itertools
  • iterate backwards

CodePudding user response:

I believe it happen because you remove a value from an array while you loop on the exist array, just copy the existing array and remove the values of the copy

import copy

roll_number = [47, 64, 69, 37, 76, 83, 95, 97]
sample_dict = {'Jhon': 47, 'Emma': 69, 'Kelly': 76, 'Jason': 97}

roll_number_b = copy.deepcopy(roll_number)
for a in roll_number:
    if a not in sample_dict.values():
        roll_number_b.remove(a)

print(roll_number_b)

#output: [47, 69, 76, 97]

CodePudding user response:

I would use a list comprehension:

[x for x in roll_number if x in sample_dict.values()]

[47, 69, 76, 97]

You can see the example in this question:

How to remove items from a list while iterating?

CodePudding user response:

It is because the result is being updated in the loop.

To understand the behavior of the code, consider this example:

>>> lst = [1, 2, 3]
>>> lst.pop(0)    
1
>>> lst.pop(1)
3

You can obtain the expected output with this code (using the while loop and only incrementing the loop counter when the element does not remove):

i = 0
while i < len(roll_number):
    if roll_number[i] not in sample_dict.values():
        roll_number.pop(i)
    else:
        i  = 1

Output

The output with the above code and with the given input is:

[47, 69, 76, 97]
  • Related