To maniero’s response explained clearly that the problem in the implemented logic was to change the structure being iterated and its examples could not be more didactic, so I would just add a summarized form of solutions:
def remove_duplicados(l1, l2):
return [i for i in l1 if i not in l2]
Thus, the function will return a new list with the elements of l1
which do not belong to the l2
.
l1 = [1, 2, 3, 4]
l2 = [1, 2, 5, 6]
print(remove_duplicados(l1, l2)) # [3, 4]
See working on Repl.it | Ideone
Some advantages in this solution are:
- When replacing the brackets with parentheses on return, the function will return a generator, which can save memory;
- No need to create copies of entry lists;
- The entry lists remain intact (may be useful in some cases);
- Readable solution;
Commentary:
When it comes to the memory saving mentioned in item 1, there are two observations: a) the economy is due to the fact that, by replacing the brackets with parentheses, the return of the function ceases to be a list and becomes a generator; thus, the final list is not stored in memory, as the generator calculates each item according to its use (Lazy
calculation or call-by-need). b) references to input objects remain the same within of the generator, not creating a copy of them; that is, even after the generator is defined, any change in the input lists will affect the generator.
With brackets, the return is a new list:
x = [1, 2, 3, 4, 5]
y = [2, 4]
def remove_duplicados(l1, l2):
return [i for i in l1 if i not in l2]
z = remove_duplicados(x, y)
print(type(z)) # <class 'list'>
# Apenas para demonstrar a saída:
print(list(z)) # [1, 3, 5]
See working on Repl.it | Ideone | Github GIST
With parentheses, the return is a generator:
x = [1, 2, 3, 4, 5]
y = [2, 4]
def remove_duplicados(l1, l2):
return (i for i in l1 if i not in l2)
z = remove_duplicados(x, y)
print(type(z)) # <class 'generator'>
# Apenas para demonstrar a saída:
print(list(z)) # [1, 3, 5]
See working on Repl.it | Ideone | Github GIST
As the reference of the lists remain the same, any change in them will be reflected in the result of the generator:
x = [1, 2, 3, 4, 5]
y = [2, 4]
def remove_duplicados(l1, l2):
return (i for i in l1 if i not in l2)
z = remove_duplicados(x, y)
# Alteração em y:
y.append(3)
print(type(z)) # <class 'generator'>
# Saída de z modificada devido alteração em y:
print(list(z)) # [1, 5]
See working on Repl.it | Ideone | Github GIST
Items 2 and 3 are complementary, because if the problem demands that the lists of entries should remain intact after the execution of the function, using the comprehensilist on or the generator will not need to create a memory copy of the list to modify it; the return itself will be a new list only with the desired items.
Already item 4 is quite subjective, but I, particularly, think the solution is much more readable:
def remove_duplicates(source, reference):
return (item for item in source if item not in reference)
Another alternative is to use set subtraction with:
L1 = list(set(L1) - set(L2))
– Isac
When removing elements from the L1 array you are breaking the index. This should generate an explicit error, but I don’t know how python treats it. The correct is to use while, that is, while L1 occurs in L2
– Marcelo