patternpythonMinor
Remove last odd number from number list in Python
Viewed 0 times
lastnumberremovepythonlistfromodd
Problem
The simplified question is:
Given a list of numbers, write a Python script that will remove the last odd number from the list.
One of the challenges is if the last odd number appears multiple times, some approaches will remove the first occurrence of that number, rather than the last.
One solution that I have is to find the max index for the odd numbers and then pop that number from the list:
This works, but I feel like there's got to be a better way. I've thought about reversing the list, removing the first odd number and then re-reversing:
This also works, and feels cleaner, but if anyone can provide advice on preferred methods/more Pythonic approaches, it'd be much appreciated!
Given a list of numbers, write a Python script that will remove the last odd number from the list.
One of the challenges is if the last odd number appears multiple times, some approaches will remove the first occurrence of that number, rather than the last.
One solution that I have is to find the max index for the odd numbers and then pop that number from the list:
def remove_last_odd(numbers):
count = 0
for num in numbers:
if num%2 == 1:
max = count
count += 1
print max
numbers.pop(max)
def run():
numbers = [1, 7, 2, 34, 8, 7, 2, 5, 14, 22, 93, 48, 76, 15, 7]
print numbers
remove_last_odd(numbers)
print numbers
run()This works, but I feel like there's got to be a better way. I've thought about reversing the list, removing the first odd number and then re-reversing:
# use this instead of remove_last_odd function
def remove_backwards(numbers):
rev_num = numbers[::-1]
for num in rev_num:
if num % 2 == 1:
rev_num.remove(num)
numbers = rev_num[::-1]
return numbersThis also works, and feels cleaner, but if anyone can provide advice on preferred methods/more Pythonic approaches, it'd be much appreciated!
Solution
By my interpretation, if the list contains no odd numbers, then the function should make no change. Your first function, since it unconditionally ends with
The first implementation is inefficient, since it examines the entire list from the beginning.
The second function, as you noted, is inefficient in that it makes two copies of the list. Furthermore,
I would write a solution this way. This function mutates the list, and also indicates which index was removed, if any.
Here is another way to do it, using
numbers.pop(max), will crash with an UnboundLocalError: local variable 'max' referenced before assignment.count += 1 is awkward. Counting loops are normally written using some kind of range() or enumerate().The first implementation is inefficient, since it examines the entire list from the beginning.
The second function, as you noted, is inefficient in that it makes two copies of the list. Furthermore,
rev_num.remove(num) is fully O(n): it performs another linear search, and then it copies the rest of the elements to fill the hole.I would write a solution this way. This function mutates the list, and also indicates which index was removed, if any.
def remove_last_odd(numbers):
for i in range(len(numbers) - 1, -1, -1):
if numbers[i] % 2:
numbers.pop(i)
return i
return NoneHere is another way to do it, using
enumerate() and reversed(), which iterates backwards without copying the list. Note that it returns a negative index.def remove_last_odd(numbers):
for i, num in enumerate(reversed(numbers), 1):
if num % 2:
numbers.pop(-i)
return -i
return NoneCode Snippets
def remove_last_odd(numbers):
for i in range(len(numbers) - 1, -1, -1):
if numbers[i] % 2:
numbers.pop(i)
return i
return Nonedef remove_last_odd(numbers):
for i, num in enumerate(reversed(numbers), 1):
if num % 2:
numbers.pop(-i)
return -i
return NoneContext
StackExchange Code Review Q#120890, answer score: 7
Revisions (0)
No revisions yet.