views:

116

answers:

4

Hey, I was trying to delete an item form a list (without using set):

list1 = []
for i in range(2,101):
    for j in range(2,101):
        list1.append(i ** j)
list1.sort()
for k in range(1,len(list1) - 1):
    if (list1[k] == list1[k - 1]):
        list1.remove(list1[k])
print "length = " + str(len(list1))

The set function works fine, but i want to apply this method. Except I get:

 IndexError: list index out of range

on the statement:

 if (list1[k] == list1[k - 1]):

Edited to add (Thanks to Ned Batchelder) the working code is:

list1 = []
for i in range(2,101):
 for j in range(2,101):
   list1.append(i ** j)
list1.sort()
k = 0
while k < len(list1) - 1: # while loop instead of for loop because "The range function is evaluated once before the loop is entered"
 k += 1
 if (list1[k] == list1[k - 1]):
  list1.remove(list1[k])
  list1.sort()
  k -= 1 # "If you find a duplicate, you don't want to move onto the next iteration, since you'll miss potential runs of more than two duplicates"
print "length = " + str(len(list1))
+2  A: 

Instead of removing items Write a list comprehension of the things you want in the new list:

list1[:] = [list1[k] for k in range(1,len(list1) - 1) 
                     if not list1[k] == list1[k - 1] ]

Your method breaks because you remove items from the list. When you do that, the list becomes shorter and the next loop iteration has skipped a item. Say you look at k=0 and L = [1,2,3]. You delete the first item, so L = [2,3] and the next k=1. So you look at L[1] which is 3 -- you skipped the 2!

So: Never change the list you iterate on

THC4k
It's a successful method, but why mine doesn't work ?
Goblin
+3  A: 

It looks as if you're trying to uniquify a list (clarification would be awesome) so take a look here: http://www.peterbe.com/plog/uniqifiers-benchmark

There is also this question here on SO: http://stackoverflow.com/questions/89178/in-python-what-is-the-fastest-algorithm-for-removing-duplicates-from-a-list-so-t

Nick Presta
It's nice to have it all in one place, bookmarked.
cji
unique and set work fine, my question is: What's wrong with my code ?
Goblin
+1  A: 

You can use del :

l = [1, 2, 3, 4]
del l[2]
print l
[1, 2, 4]
Guillaume Lebourgeois
Why a -1 ? I might have not understood the question in the first place then ?
Guillaume Lebourgeois
del and list1.remove are the same.The problem isn't here !
Goblin
+5  A: 

Your code doesn't work because in your loop, you are iterating over all the indexes in the original list, but shortening the list as you go. At the end of the iteration, you will be accessing indexes that no longer exist:

for k in range(1,len(list1) - 1):
    if (list1[k] == list1[k - 1]):
        list1.remove(list1[k])

The range function is evaluated once before the loop is entered, creating a list of all the indexes in the list. Each call to remove shortens the list by one, so if you remove any elements, you're guaranteed to get your error at the end of the list.

If you want to use a loop like this, try:

k = 1
while k < len(list1):
    if list1[k] == list1[k-1]:
        del list1[k]
    else:
        k += 1

I fixed a few other things:

  1. You don't need parentheses around the condition in Python if statements.
  2. If you find a duplicate, you don't want to move onto the next iteration, since you'll miss potential runs of more than two duplicates.
  3. You want to start from index 1, not zero, since k=0 will access list1[-1].
Ned Batchelder
- "The range function is evaluated once before the loop is entered"and "If you find a duplicate, you don't want to move onto the next iteration, since you'll miss potential runs of more than two duplicates."that the answer i was looking for, thanks !
Goblin