This solution seems to meet your criteria:
xs = [1, 2, 3, 3, 4, 5, 6, 4, 1]
while True:
for i, x in enumerate(xs):
try:
del xs[xs.index(x, i+1)]
break
except ValueError:
continue
else:
break
print(xs)
@cresht pointed out the previous version created a new list in a slice - that may be the case, but I've fixed that here, and the new solution is even more brief.
By the way, I prefer the look of the solution offered by @cresht, but that loops through the list twice explicitly while having to do another lookup in .pop()
- it'd be worth checking which is faster to pick the winner.
Edit, I tested, mine's a bit faster:
from timeit import timeit
def dedupe(xs):
while True:
for i, x in enumerate(xs):
try:
del xs[xs.index(x, i+1)]
break
except ValueError:
continue
else:
break
def remove_duplicates(arr: list) -> None:
for i, x in enumerate(arr):
for j, y in enumerate(arr):
if x == y and i != j:
arr.pop(j)
def test_dedupe():
xs = [1, 2, 3, 3, 4, 5, 6, 4, 1]
dedupe(xs)
def test_remove_duplicates():
xs = [1, 2, 3, 3, 4, 5, 6, 4, 1]
remove_duplicates(xs)
print(timeit(test_dedupe))
print(timeit(test_remove_duplicates))
Result:
1.7659466000004613
2.694205100000545
Both solutions meet the criteria, but this one is just a bit faster. (by default, timeit
runs them a million times)
Note that doing something like what @schmulvad proposes is of course the fastest and arguably best solution - but I don't think it meets the criteria of the problem:
def test_simple():
xs = [1, 2, 3, 3, 4, 5, 6, 4, 1]
xs = list(dict.fromkeys(xs))
print(timeit(test_simple))
Result:
0.4907456999972055
Fast, but creates a new copy of the original (not a list, but still a copy).