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

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

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

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

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

Ответы [ 5 ]

17 голосов
/ 01 мая 2010

Выход в первом матче действительно прост: вместо вычисления полного понимания списка (затем отбрасывания всего, кроме первого элемента), используйте next вместо genexp. Предположим, например, что вы хотите -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 - постоянное улучшение языка и его встроенных функций! -)

5 голосов
/ 01 мая 2010

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

>>> lst = [None, None, None, "foo", None]
>>> for i, item in enumerate(lst):
...   if item: break
... else:
...   print "not found"
... 
>>> i
3
4 голосов
/ 01 мая 2010

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

1 голос
/ 01 мая 2010
[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, поскольку они создают список всех несовпадающих индексов, прежде чем вы получите интересующий индекс.

0 голосов
/ 01 мая 2010

Глупое решение на основе 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 :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...