The filter and list comprehensions are ok for your example, but they have a couple of problems:
- They make a copy of your list and return the new one, and that will be inefficient when the original list is really big
- They can be really cumbersome when the criteria to pick items (in your case, if name[-5:] == 'Smith') is more complicated, or has several conditions.
Your original solution is actually more efficient for very big lists, even if we can agree it's uglier. But if you worry that you can have multiple 'John Smith', it can be fixed by deleting based on position and not on value:
names = ['Jones', 'Vai', 'Smith', 'Perez', 'Smith']
toremove = []
for pos, name in enumerate(names):
if name[-5:] == 'Smith':
toremove.append(pos)
for pos in sorted(toremove, reverse=True):
del(names[pos])
print names
We can't pick a solution without considering the size of the list, but for big lists I would prefer your 2-pass solution instead of the filter or lists comprehensions