2

I'm trying to move the odd numbers in this list to the end without using an external list. When I run the code, it moves half of the odd numbers over, and leaves the other half where they were. The overall output is correct if I run the code twice on the list, but I should only have to run it once, right? What am I doing wrong?

a = [3, 4, 55, 13, 6, 19, 33, 10, 11, 45]


for ind, val in enumerate(a):
    if val % 2 != 0:
       a.pop(ind)
       a.append(val)

print a

Thanks.

Jordan Cagney
  • 787
  • 1
  • 5
  • 8

3 Answers3

1

This is because, as a general rule, you shouldn't iterate through and modify the same list at the same time. The indices get thrown off!

As you go through and modify the list, not all of the elements actually get cycled through. The a that you are popping is a different list with different indicies after your first change to the list, but you are still using the enumeration of the original version for your loop.

Alex K
  • 8,269
  • 9
  • 39
  • 57
  • gotcha, makes sense. thanks. any way to write this code better? – Jordan Cagney Dec 07 '15 at 20:47
  • You would probably like this link: http://danishmujeeb.com/blog/2014/01/basic-sorting-algorithms-implemented-in-python – Alex K Dec 07 '15 at 20:50
  • To answer that question, you should take an algorithms class and see for yourself the different kinds of algorithms that there are. There are plenty of ways to do it. – Alex K Dec 07 '15 at 20:50
1

You could use pythons sorting methods (sorted() or someList.sort()) and pass a special key function to it:

>>> sorted(a, key = lambda element: element%2 != 0)
[4, 6, 10, 3, 55, 13, 19, 33, 11, 45]

This is possible because Python sorts are guaranteed to be stable und therefore when multiple records have the same key, their original order is preserved.

elegent
  • 3,857
  • 3
  • 23
  • 36
0

Your approach has two problems,

  1. you modify the list on which you iterate
  2. you don't test if the number that slides into the position occupied by an odd number is odd itself

To obviate with 1., you simply can iterate on the indices of your list but to obviate 2., you must start from the end of the list and going towards the beginning, using negative indices.

Executing the following code

a = [3, 4, 55, 13, 6, 19, 33, 10, 11, 45]
for i in range(len(a)):
    j = -1-i
    if a[j]%2:
        a.append(a[j]) ; a.pop(j-1) # j-1 because our list is temporarily longer...
print a

gives you the following output

[4, 6, 10, 45, 11, 33, 19, 13, 55, 3]
gboffi
  • 22,939
  • 8
  • 54
  • 85