0

I have a simple function to remove lines from a block of text (output from another program that I'd like to clean up). For some reason, it removes some lines and not others.

def remover(lst):
    for no, line in enumerate(lst):
        if line.startswith('[') or line.startswith('{'):
            print(no, line)
            lst.remove(line)
    return lst

I have a string like the following:

msg = '''Beginning process for 09/06/2016
         [datetime.date(2016, 9, 6), datetime.date(2016, 9, 7)]
         [(48614, 'snacks', datetime.datetime(2016, 9, 6, 8, ...))]
         [{'recipe': 'pb&j', 'discharge_times': [datetime.da ...]}]
         {'recipe': 'mayo', 'discharge_times': [datetime.dat ...]}
         {'RX 360': 1402.0, 'QR 1038': 69255.0, 'FZ 790': 52 ...}
         Order created: 580
         1 order was successfully created.
         1 order was also successfully processed.'''

Which I pass to the function as a list using the splitlines method:

remover(msg.splitlines())

That outputs this:

1 [datetime.date(2016, 9, 6), datetime.date(2016, 9, 7)]
2 [(48614, 'snacks', datetime.datetime(2016, 9, 6, 8, ...))]
4 {'recipe': 'mayo', 'discharge_times': [datetime.dat ...]}

and returns this (failed to remove lines 3 and 5):

'''Beginning process for 09/06/2016
[{'recipe': 'pb&j', 'discharge_times': [datetime.da ...]}]
{'RX 360': 1402.0, 'QR 1038': 69255.0, 'FZ 790': 52 ...}
Order created: 580
1 order was successfully created.
1 order was also successfully processed.'''

If I run it through the function several times, it eventually removes all the lines. It also works with different lists, but not this one for some reason.

Am I missing something simple? Why doesn't this work as expected?

Jon
  • 132
  • 1
  • 16
  • 2
    You are removing items from list that you are iterating over. – Tomasz Plaskota Sep 07 '16 at 13:10
  • 1
    You are deleting from a list while iterating over it. Because the next *index* for the list iterator is not updated, that results in items being skipped. Create a copy of the list first and iterate over that, or use a list comprehension to filter. – Martijn Pieters Sep 07 '16 at 13:10
  • You are moving items in your list around (by deleting other items) while still trying to iterate over them. Standard problem. You can use a list comprehension instead: `mylines = [ "foo", "bar", "baz" ]; [ ll for ll in mylines if ll[0]=="b" ]`. – D-Von Sep 07 '16 at 13:12
  • Ah - I knew it was something simple. Great answer - thanks! – Jon Sep 07 '16 at 13:13
  • you also need to use `remover(map(lambda x:x.strip(),msg.splitlines()))` or else there would be space in the beginning ot the lines – vks Sep 07 '16 at 13:15

0 Answers0