简体   繁体   中英

How to find the index of the last odd number in a list, without reversing the list?

Have this so far, and essentially want to get there is something wrong with the position of last_odd as the compiler says the pop index is out of range?

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 = numbers[num]
              
    if has_odd:
        numbers.pop(last_odd)
        
numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 6]

As @DeepSpace said, list.pop will

Remove the item at the given position in the list, and return it. If no index is specified, a.pop() removes and returns the last item in the list.

So basically, the solution to your problem would be to replace last_odd = numbers[num] with last_odd = num .

list.pop() receive index as argument and remove the value. So, last_odd should be assigned to num instead of numbers[num]

Your function doesn't have return value yet. It should return numbers list.

def remove_last_odd(numbers):
    for num in range(len(numbers)):
        if numbers[num] % 2 == 1:
            last_odd = num
    numbers.pop(last_odd)
    return numbers

numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 6]
print(remove_last_odd(numbers))

# [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 6]

Or iterating numbers value and using remove() method instead of pop() :

def remove_last_odd(numbers):
    for num in numbers:
        if num % 2: last_odd = num
    numbers.remove(last_odd)
    return numbers

numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 6]
print(remove_last_odd(numbers))

# [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 6]

No need to reverse the list but you can search it in reverse.

def remove_last_odd(numbers):
    for i in range(len(numbers)-1, -1, -1):
        if numbers[i] & 1:
            numbers.pop(i)
            break

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

remove_last_odd(numbers)

print(numbers)

Output:

[1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 6]

Option:

If you insist on a 'forward' search then:

def remove_last_odd(numbers):
    ri = -1
    for i, v in enumerate(numbers):
        if v & 1:
            ri = i
    if ri >= 0:
        numbers.pop(ri)

To get the index of the last odd element you can use the reversed() iterator which will not reverse the original list object.

A quick way to get the index is:

   >>> numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 6]
   >>> -next(filter(lambda v: v[1]%2==1, enumerate(reversed(numbers))))[0] 
   -1

Even for very large lists with a lot of even numbers at the end the result will be delivered quite quick (compared with the proposed code):

   >>> from timeit import timeit
   >>> def find_last_odd(numbers):
           for num in range(len(numbers)):
               if numbers[num] % 2 == 1:
                   last_odd = num
           return last_odd
   >>> numbers2=numbers+([2]*10000) # create a list with 10000 even numbers at the end!
   >>> timeit(lambda: find_last_odd(numbers2),number=100)
   0.5675344999999936
   >>> timeit.timeit(lambda: -next(filter(lambda v: v[1]%2==1, enumerate(reversed(numbers2)))).__getitem__(0),number=100)
   0.10892959999998197
    

Remove the item at the given position in the list, and return it. If no index is specified, a.pop() removes and returns the last item in the list.

So basically, the solution to your problem would be to replace last_odd = numbers[num] with last_odd = num.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM