Skip to content Skip to sidebar Skip to footer

In Python, How Can I Find The Index Of The First Item In A List That Is NOT Some Value?

Python's list type has an index(x) method. It takes a single parameter x, and returns the (integer) index of the first item in the list that has the value x. Basically, I need to i

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?"