I suppose the Pythonic way is to use set, which I just learned about. Before I learned about set, I tried the following method which didn't work. Can someone explain what is wrong with this? I got an index out of range error, but I thought the code would never run past the index range for the list as it is written. Please explain what happened.
#!/usr/bin/python
# Remove dupes from a list
def Uniq_list(x):
for elem in range(len(x)):
if ( elem == 0 ):
next
else:
if (x[elem] == x[(elem - 1)]):
x.pop(index(x[elem])
return x
mylist = ['1', '1', '2', '1', '3', '2']
print Uniq_list(mylist)
1 Answer 1
The for
loop produces the range()
object just once, but in the loop you are removing elements from the list, making it shorter.
This leads to another problem: you'll be skipping elements. If you remove element 1, all elements after it shift up one position; element 2 is now element 1, etc. But your loop never takes this into account, so it'll skip the element now moved from position 2 to 1.
This is compounded by the fact you only use the preceding element to test set membership against; the skipped element is suddenly the value against which another value is being tested. They could well be different but that doesn't mean earlier elements are not going to be equal.
Further issues: You used an unnamed index()
function in your code which means we cannot verify what it does. If it works like the list.index()
method you'd be removing the first occurrence of the value from the list object. This could work, but you already had elem
as an index into the list, why search for it again?
The next
entry on it's own line is just a reference to the next()
function, without ever calling it. As such, it is a no-op. You probably meant to use the continue
statement here instead.
A simpler version would have been:
for i in range(len(x), -1, -1):
if x[i] in x[:i]:
del x
e.g. starting from the end of the list, if the current element is present in the list before this position, remove it. However, using a set would be far more efficient still.
-
Thanks very much, I will accept when time limit allows me to do so.GL2014– GL20142014年05月24日 14:34:26 +00:00Commented May 24, 2014 at 14:34
-
My usage of next was intended as a method to skip testing x[0] against x[0 - 1]. I wanted a noop in the sense that I wanted to jump to the next iteration in the loop if elem evaluates to 0. Is that not what it would be doing?GL2014– GL20142014年05月24日 14:38:05 +00:00Commented May 24, 2014 at 14:38
-
@GreggLeventhal: No, that's what the
continue
statement does, though.Martijn Pieters– Martijn Pieters2014年05月24日 14:38:45 +00:00Commented May 24, 2014 at 14:38 -
1@GreggLeventhal: it is not needed here, really; the
else
branch is never entered if theif
statement was picked. You could just have doneif elem != 0: ...
instead.Martijn Pieters– Martijn Pieters2014年05月24日 14:39:28 +00:00Commented May 24, 2014 at 14:39 -
Darn, I wasn't sure if it was next or continue. Thanks again!GL2014– GL20142014年05月24日 14:39:52 +00:00Commented May 24, 2014 at 14:39
next
doesn't do anything; it is a no-op as it just references the built-in function.index()
function?