So say I have, list1 = ['the dog', 'the cat', 'cat dog', 'the dog ran home']
and sub_string = 'the dog'
how can I return list2 = ['the dog', 'the cat', 'cat dog']
i.e, return a list with the last occurrence of the substring removed?
No built-in will help much you here, since scanning for a substring in a list
isn't a supported feature, and doing so in reverse order is doubly hard. List comprehensions won't do much good either, since making them stateful enough to recognize when you've found your needle would involve adding side-effects to the list comprehension, which makes it cryptic and violates the purpose of functional programming tools. So you're stuck doing the looping yourself:
list2 = []
list1iter = reversed(list1) # Make a reverse iterator over list1
for item in list1iter:
if sub_string in item: # Found item to remove, don't append it, we're done
break
list2.append(item) # Haven't found it yet, keep item
list2.extend(list1iter) # Pull all items after removed item
list2.reverse() # Put result back in forward order
An alternative approach would be to scan by index, allowing you to del
it; this might be a better solution if you want to modify list1
in place, rather than making a new list
:
for i, item in enumerate(reversed(list1), 1):
if sub_string in item:
del list1[-i]
break
That solution is adaptable to making a new copy by simply changing all references to list1
to list2
, and adding list2 = list1[:]
before the loop.
In both cases, you can detect if an item was found at all by putting an else:
block on the for
; if the else
block triggers, you didn't break
, because sub_string
wasn't found anywhere.