Подтвердить что ты не робот

В Python, как я могу найти индекс первого элемента в списке, который НЕ является некоторым значением?

Тип списка Python имеет метод index (x). Он принимает один параметр x и возвращает индекс (целочисленный) первого элемента в списке, который имеет значение x.

В принципе, мне нужно инвертировать метод index (x). Мне нужно получить индекс первого значения в списке, который НЕ имеет значения x. Я бы, вероятно, мог бы просто использовать функцию, которая возвращает индекс первого элемента со значением!= Нет.

Я могу думать о реализации цикла for for с переменной переменной счетчика, но я чувствую, что что-то не хватает. Есть ли существующий метод или однострочная конструкция Python, которая может справиться с этим?

В моей программе ситуация возникает, когда я обрабатываю списки, возвращаемые из сложных регулярных совпадений. Все, кроме одного элемента в каждом списке, имеют значение None. Если мне просто нужна строка с совпадением, я мог бы использовать представление списка, например "[x для x в [my_list], если x не является None]", но мне нужен индекс, чтобы выяснить, какая группа захвата в моем регулярном выражении фактически вызвала матч.

4b9b3361

Ответ 1

Выход из первого совпадения очень просто: вместо вычисления полного понимания списка (затем отбрасывая все, кроме первого элемента), используйте next над геном xp. Предположим, например, что вы хотите -1, когда ни один элемент не удовлетворяет условию != x,

return next((i for i, v in enumerate(L) if v != x), -1)

Это синтаксис Python 2.6; если вы застряли с 2.5 или более ранними версиями, .next() - это метод genexp (или другого итератора) и не принимает значение по умолчанию, например, как -1 (так что если вы не хотите видеть StopIteration исключение вам придется использовать try/except). Но тогда есть причина, по которой после 2.5 были выпущены релизы - непрерывное совершенствование языка и его встроенных модулей! -)

Ответ 2

Использование понимания списка, когда вам нужен только первый, просто чувствует слизь (мне). Используйте for-loop и выйдите раньше.

>>> lst = [None, None, None, "foo", None]
>>> for i, item in enumerate(lst):
...   if item: break
... else:
...   print "not found"
... 
>>> i
3

Ответ 3

enumerate() возвращает итератор, который дает кортеж текущего индекса итеративного, а также самого элемента.

Ответ 4

[i for i, x in enumerate(my_list) if x != value][0]

Если вы не уверены, есть ли несоответствующий элемент, используйте это вместо:

match = [i for i, x in enumerate(my_list) if x != value]
if match:
    i = match[0]
    # i is your number.

Вы можете сделать это еще более "функциональным" с помощью itertools, но вы скоро достигнете точки, в которой проще для цикла. Даже вышеприведенные решения не так эффективны, как цикл for, поскольку они строят список всех несоответствующих индексов, прежде чем тянуть интерес.

Ответ 5

Глупое решение на основе itertools:)

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

Все это просто для того, чтобы воспользоваться подсчетом itertools.count:)