Reputation: 57
kind of a newbie to Python and I've looked around a bit but haven't found a satisfying answer to my question. I'm doing some practice problems and I want to make a method that gets rid of duplicate values in a list. So far, this is my code:
def noDouble(nums):
for x in xrange(len(nums) - 2):
if nums[x] == nums[x + 1]:
nums.pop(x)
x -= 1
return nums
What I want to happen is that if there's a duplicate, pop off one of the duplicates and then move back again (so that if there are, say, 3 instances of the same number, it'll get rid of al of them by 'rewinding').
I'm looking for an explanation for why my code doesn't work as well as an explained solution and I'd really appreciate any and all help. Thanks.
Upvotes: 0
Views: 2991
Reputation: 6935
As far as I understand it, the for
loop isn't a simple increment like it is in C or Java; Python will actually force x
back to the value it's expected to be for the next loop iteration. So decrementing x
won't have the effect of adding more loop iterations, because it will be forcibly reset.
for x in range(10):
x -= 1
print x
will yield
-1
0
1
2
3
4
5
6
7
8
EDIT: here's a possibility for what you're trying to do, though the accepted answer is easier for your specific use case. Use while
instead of for
:
limit = len(nums) - 1
x = 0
while x < limit:
if nums[x] == nums[x+1]:
nums.pop(x)
x -= 1
x += 1
return nums
Though this code may still fail with an IndexError
because of how you're accessing list elements. But still, that's how you'd add extra iterations.
Upvotes: 2
Reputation: 48546
Because for
doesn't count numbers; it iterates over a sequence. Every time the body of the loop executes, x
is set to the next value produced by the xrange
. The for
statement couldn't care less what x
is at the end of the loop.
You really shouldn't modify a list within a loop over it, anyway. The easier way to do this is to build a new list:
def remove_doubles(old):
new = []
for item in old:
if new and item == new[-1]:
continue
new.append(item)
return new
Of course, the really easy way to remove duplicates is list(set(foo))
. But that will remove all duplicates, not just adjacent ones, and probably destroy the item order too.
Upvotes: 3
Reputation: 3572
Generally you never want to manipulate the counter in a loop (aside from setting it to break out of the loop). For a similar reason, you don't want to saw a branch you are sitting on, when cutting down a tree :-)
The safer route (compared to nested loops) is to build a set of operations in one loop, then pass this set to a second loop (each loop one level deep).
Upvotes: 0