I get data in the following format:
[-2, -2, 0, 0, 0, 0, 0]
[-2, 20, -1, 0, 3, 0, 0]
with each line being a different input. The lists could be longer than 7 elements. I need to return the index position of the last non-zero element, so:
[-2, -2, 0, 0, 0, 0, 0]
>>> 1
[-2, 20, -1, 0, 3, 0, 0]
>>> 4
The following code does this most of the time:
def getIndex(list):
for element in reversed(list):
if element != 0:
return list.index(element)
However, it doesn't work when there are two of the same numbers, as in the first example above, which returns 0
because -2
is in both the 0th and 1st position of the list.
So how to get the index of the last non-zero element of a list, even when there are elements with the same value?
Any element in list can be accessed using zero based index. If index is a negative number, count of index starts from end. As we want last element in list, use -1 as index.
nonzero() function is used to Compute the indices of the elements that are non-zero. It returns a tuple of arrays, one for each dimension of arr, containing the indices of the non-zero elements in that dimension. The corresponding non-zero values in the array can be obtained with arr[nonzero(arr)] .
nonzero. Return the indices of the elements that are non-zero. Returns a tuple of arrays, one for each dimension of a, containing the indices of the non-zero elements in that dimension.
Use the nonzero() Function to Find the First Index of an Element in a NumPy Array. The nonzero() function returns the indices of all the non-zero elements in a numpy array.
Your solution changes the list constantly, I think even the naive for
loop is better:
last_nonzero_index = None
for idx, item in enumerate(originalList):
if item != 0:
last_nonzero_index = idx
Here is a pythonic and optimized approach using itertools.takewhile()
:
from itertools import takewhile
from operator import not_
len(lst) - sum(1 for _ in takewhile(not_, reversed(lst))) - 1
Demo:
In [115]: lst = [-2, -2, 0, 0, 0, 0, 0]
In [118]: len(lst) - sum(1 for _ in takewhile(lambda x : not bool(x), lst[::-1])) - 1
Out[118]: 1
In [119]: lst = [-2, 20, -1, 0, 3, 0, 0]
In [120]: len(lst) - sum(1 for _ in takewhile(lambda x : not bool(x), lst[::-1])) - 1
Out[120]: 4
Here is a benchmarck with another answers on a longer list:
In [141]: lst = lst * 1000
In [142]: %timeit len(lst) - len(list(takewhile(not_, reversed(lst)))) - 1
1000000 loops, best of 3: 758 ns per loop
In [143]: %timeit get_last_non_zero_index(lst)
1000000 loops, best of 3: 949 ns per loop
In [146]: %timeit index_of_last_nonzero(lst)
1000000 loops, best of 3: 590 ns per loop
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With