1

When i try for loop to remove all a's from list here is my code:

list5 = ["a","b","a","b","a","b","c"]
def remove_values_from_list(_list, val):
        for val in _list:
            _list.remove(val)
remove_values_from_list(list5, "a")
print(list5)

it return's:

["b","b","b"]

and when i use while instead of for it returns:

list5 = ["a","b","a","b","a","b","c"]
def remove_values_from_list(_list, val):
        while val in _list:
            _list.remove(val)
remove_values_from_list(list5, "a")
print(list5)



["b","b","b","c"]

Can someone explain me why does for loop doesn't return last c?

Sociopath
  • 13,068
  • 19
  • 47
  • 75
Chris_007
  • 829
  • 11
  • 29
  • 1
    Where is your `while loop`? – DirtyBit Jan 31 '19 at 06:33
  • 1
    @user5173426 in the same code change while instead of for. – Chris_007 Jan 31 '19 at 06:35
  • 2
    @BarotShalin Include that part too in your question. – Sociopath Jan 31 '19 at 06:36
  • Possible duplicate of [When to use "while" or "for" in Python](https://stackoverflow.com/questions/920645/when-to-use-while-or-for-in-python) – Andreas Jan 31 '19 at 06:38
  • Why should your for loop return `["b","b","b"]` when it actually should return `['b', 'b', 'b', 'c']` – DirtyBit Jan 31 '19 at 06:40
  • @user5173426 coz it's really bad idea to remove elements using for loop. As you remove elements list gets smaller. – Sociopath Jan 31 '19 at 06:41
  • Trimming a list while iterating through it is tricky. – hpaulj Jan 31 '19 at 07:51
  • For the first example, the `val` parameter you're passing to your function gets overwritten and the for-loop just loops over all elements - it only looks like it's almost doing what you want because it's skipping every second element (in short: removing elements using a for-loop is not a good idea). The while loop is basically repeatedly checking the entire list looking for the element ("while `a` is in the list, remove `a`"), which is slow. Related: [How to remove items from a list while iterating?](https://stackoverflow.com/questions/1207406) – Bernhard Barker Jan 31 '19 at 11:10

2 Answers2

0

You need to fix your for loop first, it should be:

def remove_values_from_list(_list, val):
        for _val in _list:
            if _val == val:
                _list.remove(val)
        print(_list)

OUTPUT:

['b', 'b', 'b', 'c']

and then so would the while loop:

def remove_values_from_list(_list, val):
    while(val in _list):
        _list.remove(val)
    print(_list)

remove_values_from_list(list5, "a")

OUTPUT:

['b', 'b', 'b', 'c']

EDIT:

You should alter your while loop a bit like:

while True:
    if val not in _list:
        break
    else:
        _list.remove(val)
print(_list)

EDIT 2:

Thanks @Dukeling for the catch:

You cannot remove elements (consecutive ones) from a list while iterating over it using a for-loop. For it, we can iterate over a copy of it like:

def remove_values_from_list(_list, val):

    for _val in _list[:]:
        if _val == val:
            _list.remove(_val)
    print(_list)

list5 = ["a", "a"]

remove_values_from_list(list5, "a") 

OUTPUT:

[]
DirtyBit
  • 16,613
  • 4
  • 34
  • 55
0

It's because you are using val in for loop and the parameter your function receives is called val too.

Try something like this:

def remove_values_from_list(_list, val):
    for v in _list:
        if v == val:
            _list.remove(v)

More efficient way to do this is:

def remove_values_from_list(_list, val):
    return list(filter(lambda x: x!=val, _list ))
Vaibhav Vishal
  • 6,576
  • 7
  • 27
  • 48