This is a variation of the other answers that use:
- reversed()
- list comprehension
- list.remove(element)
As others have pointed out, reversed()
is needed to ensure that the elements are deleted in reverse order, else, without it, when traversing forward, it will not process the record immediately to the right of the delete.
The difference is we use list comprehension to both iterate and delete the elements at the same time, so, no double traversal. We also use list comprehension to build the list of deleted elements.
a = [1,2,2,2,2,3,4,5]
deleted = [a.remove(n) or n for n in reversed(a) if n == 2]
print(deleted)
# [2, 2, 2, 2]
print(a)
# [1, 3, 4, 5]
For the values in the resultant list, we are using a.remove(n) or n
. The left-hand expression, i.e. a.remove(n)
always evaluates to None
. So the or
will always favor the right-hand expression, i.e. n
. So, the resultant list will always be the list of deleted items. This is useful when the list contains more complex objects such as dictionaries.
materials = [{"n":"silver","t":"metal" },
{"n":"iron" ,"t":"metal" },
{"n":"water" ,"t":"liquid"}]
deleted = [materials.remove(m) or m for m in reversed(materials) if m["t"] == "metal"]
print(deleted)
# [{'n': 'iron', 't': 'metal'}, {'n': 'silver', 't': 'metal'}]
print(materials)
# [{'n': 'water', 't': 'liquid'}]
The downside of this approach is it forces a temporary list to be built which, in most cases, you will discard shortly afterward. For example, in this example, the temporary list is discarded immediately after it was built:
a = [1,2,2,2,2,3,4,5]
[a.remove(n) or n for n in reversed(a) if n == 2]
print(a)
# [1, 3, 4, 5]
The saving grace of this solution is it implements the in-place deletion with 1 succinct line of python.
except
is bad practice. Useexcept Exception
at a minimum. – Mccracken