When you remove a number and add a zero to the end of the list, your main loop (for i ...) will eventually get to the zeroes at the end. At that point you will have removed one '1' and two '5' so the count will be 3 and there will be 3 zeroes to process. Each of these zeroes will find two other zeroes in the list (replacement with another zero wont make a difference). So, in total 1+2+2+2+2 = 9 counting 1 (for the 1's) 2 (for the 5's) and three more times 2 (for each of the zeroes).
One way around this (without changing your code too much) would be to break the main loop when you reach a zero (assuming zero is not a legitimate value in the initial list)
Answer from Alain T. on Stack OverflowWhen you remove a number and add a zero to the end of the list, your main loop (for i ...) will eventually get to the zeroes at the end. At that point you will have removed one '1' and two '5' so the count will be 3 and there will be 3 zeroes to process. Each of these zeroes will find two other zeroes in the list (replacement with another zero wont make a difference). So, in total 1+2+2+2+2 = 9 counting 1 (for the 1's) 2 (for the 5's) and three more times 2 (for each of the zeroes).
One way around this (without changing your code too much) would be to break the main loop when you reach a zero (assuming zero is not a legitimate value in the initial list)
You will have to forgive me if I have this wrong, but from your example, you were adding a "0" for each duplicated number and then trying to count how many "0's" had been added to the list.
Creating a set based on the list would seem easier, and then comparing the two to my way of thinking.
mylist = [1,1,3,4,5,5,5,6]
myset = set(mylist)
print(len(mylist) - len(myset))
This would give you the answer of 3 that you were looking for.
Python: Iterate through list and remove duplicates (without using Set()) - Stack Overflow
python - Removing duplicates in lists - Stack Overflow
How to quickly remove duplicates from a list?
Good points!
Try to avoid posting code as images - it's bad when it comes to accessibility (bad eyesight, etc.), it's bad when it comes to copyability (although it's nice that we're able to emulate the 80s of typing in code from magazines) and it doesn't really work for searching.
More on reddit.comIs this a more efficient way of removing duplicates?
Videos
The issue is with "automatic" for loops - you have to be careful about using them when modifying that which you are iterating through. Here's the proper solution:
def remove_dup(a):
i = 0
while i < len(a):
j = i + 1
while j < len(a):
if a[i] == a[j]:
del a[j]
else:
j += 1
i += 1
s = ['cat','dog','cat','mouse','dog']
remove_dup(s)
print(s)
Output: ['cat', 'dog', 'mouse']
This solution is in-place, modifying the original array rather than creating a new one. It also doesn't use any extra data structures.
You can loop through the list and check if the animal has already been added.
s = ['cat','dog','mouse','cat','horse','bird','dog','mouse']
sNew = []
for animal in s:
if animal not in sNew:
sNew.append(animal)
s = sNew
The common approach to get a unique collection of items is to use a set. Sets are unordered collections of distinct objects. To create a set from any iterable, you can simply pass it to the built-in set() function. If you later need a real list again, you can similarly pass the set to the list() function.
The following example should cover whatever you are trying to do:
>>> t = [1, 2, 3, 1, 2, 3, 5, 6, 7, 8]
>>> list(set(t))
[1, 2, 3, 5, 6, 7, 8]
>>> s = [1, 2, 3]
>>> list(set(t) - set(s))
[8, 5, 6, 7]
As you can see from the example result, the original order is not maintained. As mentioned above, sets themselves are unordered collections, so the order is lost. When converting a set back to a list, an arbitrary order is created.
Maintaining order
If order is important to you, then you will have to use a different mechanism. A very common solution for this is to rely on OrderedDict to keep the order of keys during insertion:
>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]
Starting with Python 3.7, the built-in dictionary is guaranteed to maintain the insertion order as well, so you can also use that directly if you are on Python 3.7 or later (or CPython 3.6):
>>> list(dict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]
Note that this may have some overhead of creating a dictionary first, and then creating a list from it. If you donโt actually need to preserve the order, youโre often better off using a set, especially because it gives you a lot more operations to work with. Check out this question for more details and alternative ways to preserve the order when removing duplicates.
Finally note that both the set as well as the OrderedDict/dict solutions require your items to be hashable. This usually means that they have to be immutable. If you have to deal with items that are not hashable (e.g. list objects), then you will have to use a slow approach in which you will basically have to compare every item with every other item in a nested loop.
In Python 2.7, the new way of removing duplicates from an iterable while keeping it in the original order is:
>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
In Python 3.5, the OrderedDict has a C implementation. My timings show that this is now both the fastest and shortest of the various approaches for Python 3.5.
In Python 3.6, the regular dict became both ordered and compact. (This feature is holds for CPython and PyPy but may not present in other implementations). That gives us a new fastest way of deduping while retaining order:
>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
In Python 3.7, the regular dict is guaranteed to both ordered across all implementations. So, the shortest and fastest solution is:
>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']