Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

return index of last non-zero element in list

Tags:

python

list

numpy

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?

like image 222
Vincent Avatar asked Dec 27 '16 13:12

Vincent


People also ask

How do you get the index of the last element in a list?

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.

How do you find the index of a non-zero element in Python?

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)] .

What does Numpy nonzero return?

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.

How do I find the first non-zero value in an array Python?

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.


2 Answers

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
like image 78
RemcoGerlich Avatar answered Nov 07 '22 10:11

RemcoGerlich


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
like image 31
Mazdak Avatar answered Nov 07 '22 09:11

Mazdak