How to remove last odd number in a list

I have a list of numbers and I would like to remove the LAST odd number from it. This code works well only when the last odd number is not repeated throughout the list before:

numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 7]
odd_numbers = []

def remove_last_odd(numbers):
    for n in numbers:
        if n % 2 != 0:
            odd_numbers.append(n)    
    numbers.remove(odd_numbers[-1])
    return numbers

So instead of removing the last 7, I end up removing the first occurrence of 7 in my "numbers" list.

Can anyone help?

Answers


not the most efficient way but will work:

def remove_last_odd(numbers):
    rnumbers = numbers[::-1]
    for n in rnumbers:
        if n % 2 != 0:  
            rnumbers.remove(n)
            break
    return rnumbers[::-1]

basically do this: reverse list, remove first odd number, reverse again and return.


This happens because the loop iterates from first element to last element. Just reverse loop:

for n in reversed(numbers):

Use pop() instead of remove(). remove() searches for the argument value in the list and takes out the first one it finds. pop() removes the element at the specific index passed in as an argument. You'll need to refactor you're code so that you're locating the index of the last odd number, but then pop() will do as you expect.


Solution without reversing the list:

def remove_last(iterable, condition):
     result = []
     pre = []
     for x in iterable:
        if condition(x):
            result.extend(pre)
            pre = []
        pre.append(x)
    return result + pre[1:]

remove_last([1,5,6,7,8,9,10], lambda x: x&1)
>>> [1, 5, 6, 7, 8, 10]

numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 7]

_numbers = numbers[::-1]

for i, index in enumerate(_numbers):
    if i % 2 != 0:
        del(_numbers[index])
    break
print _numbers

You can use max with enumerate without reversing the list. max gives you the last index of the number that is odd. and pop takes an optional argument which is the index of the element you want to remove.

def remove_last(numbers):
    numbers.pop(max(i for i, j in enumerate(numbers) if j % 2 != 0))
    return numbers

Striving for efficiency, here's a solution that doesn't reverse the list or go through it twice.

def remove_last_odd(numbers):
    idx = len(numbers)
    last_odd = False
    while not last_odd and idx > 0:
        idx -= 1
        last_odd = (numbers[idx] % 2 != 0)

    return numbers[0:idx]

This is similar to Ness's approach, but I think a little clearer. First I reverse the list, appending each element into first_list.

Then I go through first_list item by item, using a boolean flag to identify (and skip) the first odd number, appending everything else into second_list.

Finally, I reverse second_list, appending its elements into third_list. Done.

def remove_last_odd(numbers):
    found_it = False
    first_list = []
    second_list = []
    third_list = []

    for num in numbers[::-1]:
        first_list.append(num)

    for num in first_list:

        if found_it == False:

            if num % 2 == 0:
                second_list.append(num)
            else:
                found_it = True

        else:
            second_list.append(num)

    for num in second_list[::-1]:
        third_list.append(num)

    return third_list

The solution using a For loop without reversing the list by using the index of the last odd number.

def remove_last_odd(numbers):
   has_odd = False
   last_odd = 0

   for num in range(len(numbers)):

      if numbers[num] % 2 == 1:
          has_odd = True
          last_odd =num 

      if has_odd:
          numbers.pop(last_odd)

   return numbers

Need Your Help

Custom event loop and UIKit controls. What extra magic Apple's event loop does?

iphone animation event-handling uikit event-loop

Does anyone know or have good links that explain what iPhone's event loop does under the hood?

How to dump goroutine stacktraces?

go

I have Java background, and I love to use signal QUIT to inspect Java thread dump.