2

I'm having a list of strings. I don't need some of the strings as it's a repeating header. I defined a function using while loop that should remove the strings, however I need to run the cell multiple times as the while loop stops before i=len(list_of_strings). If I run the cell multiple times, then it eventually works. What did I do wrong?

def header_eraser(list_of_strings):
    i=0
    while i < len(list_of_strings):
        if list_of_strings[i] in headers:
            del list_of_strings[i]
            i+=1
        else:
            i+=1
wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • 2
    If you're deleting an index, you don't need to increment `i` since the next index will have moved to current position – Sayse Jan 20 '21 at 15:36
  • 1
    You should probably look into list comprehensions, because deleting stuff from a list while iterating can be quite troublesome. – Mitchell Olislagers Jan 20 '21 at 15:38
  • By the way I would build another list from the previous one to avoid deleting elements while walking the list. Have a look at [list comprehension](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions). – MetallimaX Jan 20 '21 at 15:38
  • 1
    @Sayse: Ah, of course!!!! Thanks a lot, feeling stupid enough now. – Krystof Meier Jan 20 '21 at 15:39
  • @MetallimaX, MitchellOlislagers Thanks a lot, will do. – Krystof Meier Jan 20 '21 at 15:41
  • Related: [How to remove items from a list while iterating?](https://stackoverflow.com/q/1207406/4518341) – wjandrea Jan 20 '21 at 15:48

2 Answers2

1

As Sayse said in a comment:

If you're deleting an index, you don't need to increment i since the next index will have moved to current position

i.e.

def header_eraser(list_of_strings):
    i = 0
    while i < len(list_of_strings):
        if list_of_strings[i] in headers:
            del list_of_strings[i]
            # i += 1  # <- Remove this line
        else:
            i += 1

However, you might find it easier to use a list comprehension, which requires returning a new list instead of modifying the existing one:

def header_eraser(list_of_strings):
    return [s for s in list_of_strings if s not in headers]
wjandrea
  • 28,235
  • 9
  • 60
  • 81
0

When you remove an element, the length of the list changes and therefore you are skipping some elements, that's why if you run it multiple times it works.

I would suggest a for loop here, so you don't have to worry abount indexes:

def header_eraser(list_of_strings):
    new_list = []
    for s in list_of_strings:
        if s not in headers:
            new_list.append(s)
    return new_list

This can also be written as a list comprehension:

new_list = [s for s in list_of_strings if s not in headers]
dzang
  • 2,160
  • 2
  • 12
  • 21