In Python, how can I find the index of the first item in a list that is NOT some value?

前端 未结 5 380
小鲜肉
小鲜肉 2020-12-14 20:14

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.

Basica

相关标签:
5条回答
  • 2020-12-14 20:30

    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 :)

    0 讨论(0)
  • 2020-12-14 20:34
    [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.

    0 讨论(0)
  • 2020-12-14 20:36

    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!-)

    0 讨论(0)
  • 2020-12-14 20:41

    enumerate() returns an iterator that yields a tuple of the current index of the iterable as well as the item itself.

    0 讨论(0)
  • 2020-12-14 20:50

    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
    
    0 讨论(0)
提交回复
热议问题