Reputation: 1264
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?
Upvotes: 2
Views: 1775
Reputation: 1
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
Upvotes: 0
Reputation: 1
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
Upvotes: 0
Reputation: 10218
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]
Upvotes: 0
Reputation: 61225
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
Upvotes: 0
Reputation: 1808
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
Upvotes: 0
Reputation: 42758
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]
Upvotes: 1
Reputation: 59
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.
Upvotes: 1
Reputation: 75
This happens because the loop iterates from first element to last element. Just reverse loop:
for n in reversed(numbers):
Upvotes: 3
Reputation: 10740
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.
Upvotes: 4