Find the first instance of a nonzero number in a list in Python
Question:
I have a list like this:
myList = [0.0, 0.0, 0.0, 2.0, 2.0]
I would like to find the location of the first number in the list that is not equal to zero.
myList.index(2.0)
It works in this example, but sometimes the first nonzero number will be 1 or 3.
Is there a fast way of doing this?
Answers:
Use next
with enumerate
:
>>> myList = [0.0 , 0.0, 0.0, 2.0, 2.0]
>>> next((i for i, x in enumerate(myList) if x), None) # x!= 0 for strict match
3
Simply use a list comprehension:
myDict = {x: index for index, x in enumerate(myList) if x}
The indices of the nonzero elements are myDict[element]
.
What about using enumerate? Check the enumerate documentation.
def first_non_zero(mylist):
for index, number in enumerate(mylist):
if number != 0: # or 'if number:'
return index
Here’s a one liner to do it:
val = next((index for index,value in enumerate(myList) if value != 0), None)
Basically, it uses next() to find the first value, or return None
if there isn’t one. enumerate() is used to make an iterator that iterates over index,value tuples so that we know the index that we’re at.
Use filter
Python 2:
myList = [0.0, 0.0, 0.0, 2.0, 2.0]
myList2 = [0.0, 0.0]
myList.index(filter(lambda x: x!=0, myList)[0]) # 3
myList2.index(filter(lambda x: x!=0, myList2)[0]) # IndexError
Python 3: (Thanks for Matthias’s comment):
myList.index(next(filter(lambda x: x!=0, myList))) # 3
myList2.index(next(filter(lambda x: x!=0, myList2))) # StopIteration
# from Ashwini Chaudhary's answer
next((i for i, x in enumerate(myList) if x), None) # 3
next((i for i, x in enumerate(myList2) if x), None) # None
You have to handle special case.
You can use numpy.nonzero:
myList = [0.0, 0.0, 0.0, 2.0, 2.0]
I = np.nonzero(myList)
# The first index is necessary because the vector is within a tuple
first_non_zero_index = I[0][0]
# 3
Using next
with enumerate
is excellent when the array is large. For smaller arrays, I would use argmax
from NumPy so that you won’t need a loop:
import numpy as np
myList = [0.0, 0.0, 0.0, 2.0, 2.0]
myArray = np.array(myList)
np.argmax(myArray > 0)
3
Use this:
[i for i, x in enumerate(myList) if x][0]
Do the following:
print (np.nonzero(np.array(myList))[0][0])
This is more convenient, because along with finding nonzero values, this can also help to apply logic function directly. For example:
print (np.nonzero(np.array(myList)>1))
I have a list like this:
myList = [0.0, 0.0, 0.0, 2.0, 2.0]
I would like to find the location of the first number in the list that is not equal to zero.
myList.index(2.0)
It works in this example, but sometimes the first nonzero number will be 1 or 3.
Is there a fast way of doing this?
Use next
with enumerate
:
>>> myList = [0.0 , 0.0, 0.0, 2.0, 2.0]
>>> next((i for i, x in enumerate(myList) if x), None) # x!= 0 for strict match
3
Simply use a list comprehension:
myDict = {x: index for index, x in enumerate(myList) if x}
The indices of the nonzero elements are myDict[element]
.
What about using enumerate? Check the enumerate documentation.
def first_non_zero(mylist):
for index, number in enumerate(mylist):
if number != 0: # or 'if number:'
return index
Here’s a one liner to do it:
val = next((index for index,value in enumerate(myList) if value != 0), None)
Basically, it uses next() to find the first value, or return None
if there isn’t one. enumerate() is used to make an iterator that iterates over index,value tuples so that we know the index that we’re at.
Use filter
Python 2:
myList = [0.0, 0.0, 0.0, 2.0, 2.0]
myList2 = [0.0, 0.0]
myList.index(filter(lambda x: x!=0, myList)[0]) # 3
myList2.index(filter(lambda x: x!=0, myList2)[0]) # IndexError
Python 3: (Thanks for Matthias’s comment):
myList.index(next(filter(lambda x: x!=0, myList))) # 3
myList2.index(next(filter(lambda x: x!=0, myList2))) # StopIteration
# from Ashwini Chaudhary's answer
next((i for i, x in enumerate(myList) if x), None) # 3
next((i for i, x in enumerate(myList2) if x), None) # None
You have to handle special case.
You can use numpy.nonzero:
myList = [0.0, 0.0, 0.0, 2.0, 2.0]
I = np.nonzero(myList)
# The first index is necessary because the vector is within a tuple
first_non_zero_index = I[0][0]
# 3
Using next
with enumerate
is excellent when the array is large. For smaller arrays, I would use argmax
from NumPy so that you won’t need a loop:
import numpy as np
myList = [0.0, 0.0, 0.0, 2.0, 2.0]
myArray = np.array(myList)
np.argmax(myArray > 0)
3
Use this:
[i for i, x in enumerate(myList) if x][0]
Do the following:
print (np.nonzero(np.array(myList))[0][0])
This is more convenient, because along with finding nonzero values, this can also help to apply logic function directly. For example:
print (np.nonzero(np.array(myList)>1))