In Python, How Can I Find The Index Of The First Item In A List That Is NOT Some Value?
Solution 1:
Exiting at the first match is really easy: instead of computing a full list comprehension (then tossing away everything except the first item), use next
over a genexp. Assuming for example that you want -1
when no item satisfies the condition of being != x
,
return next((i for i, v in enumerate(L) if v != x), -1)
This is Python 2.6 syntax; if you're stuck with 2.5 or earlier, .next()
is a method of the genexp (or other iterator) and doesn't accept a default value like the -1
above (so if you don't want to see a StopIteration
exception you'll have to use a try
/except
). But then, there is a reason more releases were made after 2.5 -- continuous improvement of the language and its built-ins!-)
Solution 2:
Using a list comprehension when you only need the first just feels slimy (to me). Use a for-loop and exit early.
>>> lst = [None, None, None, "foo", None]
>>> for i, item in enumerate(lst):
... if item: break
... else:
... print "not found"
...
>>> i
3
Solution 3:
enumerate()
returns an iterator that yields a tuple of the current index of the iterable as well as the item itself.
Solution 4:
[i for i, x in enumerate(my_list) if x != value][0]
If you're not sure whether there's a non-matching item, use this instead:
match = [i for i, x in enumerate(my_list) if x != value]
if match:
i = match[0]
# i is your number.
You can make this even more "functional" with itertools, but you will soon reach the point where a simple for loop is better. Even the above solutions aren't as efficient as a for loop, since they construct a list of all non-matching indices before you pull the one of interest.
Solution 5:
A silly itertools-based solution:)
import itertools as it, operator as op, functools as ft
def index_ne(item, sequence):
sequence= iter(sequence)
counter= it.count(-1) # start counting at -1
pairs= it.izip(sequence, counter) # pair them
get_1st= it.imap(op.itemgetter(0), pairs) # drop the used counter value
ne_scanner= it.ifilter(ft.partial(op.ne, item), get_1st) # get only not-equals
try:
ne_scanner.next() # this should be the first not equal
except StopIteration:
return None # or raise some exception, all items equal to item
else:
return counter.next() # should be the index of the not-equal item
if __name__ == "__main__":
import random
test_data= [0]*20
print "failure", index_ne(0, test_data)
index= random.randrange(len(test_data))
test_data[index]= 1
print "success:", index_ne(0, test_data), "should be", index
All this just to take advantage of the itertools.count
counting :)
Post a Comment for "In Python, How Can I Find The Index Of The First Item In A List That Is NOT Some Value?"