0

I have a general doubt since my logic seems correct but still it gives me the wrong result. I need to understand, why this logic doesn't work smoothly.

Question is simple, please do not judge me on this basis, plus I'm new to python. So here is the question

To remove odd numbers from the provided list

My Code:

def purify(lst):
  for ele in lst:
    if ele % 2 != 0:
      lst.remove(ele)
  return lst

print purify([4, 5, 3, 4])

OUTPUT: [4,3,4] WHY?????

I know about the remove(), I have read about it, for this result, [1,2,3], it prints the correct result, but for some of the inputs, it is like insane.

The generic answer given was to make a new list and append it to the new list based upon the check whether the elem%2 == 0 and return it

But my question is that why ain't my code is working?? What is going wrong in the logic here? Thanks in advance :)

Alok
  • 8,452
  • 13
  • 55
  • 93
  • Possible duplicate of [How to remove items from a list while iterating?](https://stackoverflow.com/questions/1207406/how-to-remove-items-from-a-list-while-iterating) – SiHa Aug 29 '19 at 07:16

2 Answers2

1

Issue is while you loop when you found odd number 5 then you delete that but the loop hasn't finished yet. And you delete from that loop so, next time it iterate it will skip the number 3.

If you simply print it:

def purify(lst):
  for ele in lst:
    print(ele)
    if ele % 2 != 0:
      lst.remove(ele)
  return lst

print purify([4, 5, 3, 4])

Value is:

4
5
4
[4, 3, 4]

So, where is number 3 in iteration?

Sagar Rana Magar
  • 550
  • 1
  • 3
  • 18
  • Okay, so you're saying, while loop is going on: 4,5,3,4 -> 5 found -> Removed 5 -> Then it should go to the next number technically, how comes it is skipping 3 from the list? – Alok Aug 29 '19 at 06:57
  • It is referencing the list you are iterating and it is not copy. So, it got deleted. and number 3 come in 2 index. and skip it. – Sagar Rana Magar Aug 29 '19 at 06:58
  • You mean, **3 comes to 1st index, not 2nd**, right? – Alok Aug 29 '19 at 06:59
  • yes, you are right you take it from 0th index. Use below code you will find the right answer as i am deleting the copy not reference of list. – Sagar Rana Magar Aug 29 '19 at 07:03
  • import copy def purify(lst): lstcopy = copy.copy(lst) for ele in lst: if ele % 2 != 0: lstcopy.remove(ele) return lstcopy print purify([4, 5, 3, 4]) – Sagar Rana Magar Aug 29 '19 at 07:03
  • How does this work now Sagar? The above code, we are doing the same thing, it is just that we're making a copy of the array into the new list, but doing the same thing. How come the index issue is gone? – Alok Aug 29 '19 at 07:08
  • Your logic is right but when it found any odd number in list you delete it from the current iterating loop and loop works on the index basis like 0, 1, 2, etc. When you delete the number 5 the index is 1 and it got delete from the lst and number 3 comes to index 1, and it will not get iterate it will skip that one. So, instead of directly deleting it you should make a copy. – Sagar Rana Magar Aug 29 '19 at 07:14
1

Here is a vectorized method to go about it via numpy arrays,

import numpy as np

ar1 = np.array([4, 5, 3, 4])
ar1[ar1 % 2 == 0]
#array([4, 4])
#or coerce to list
list(ar1[ar1 % 2 == 0])
#[4, 4]
Sotos
  • 51,121
  • 6
  • 32
  • 66