Python: возвратите индекс первого элемента списка, который делает переданную функцию верной

py2exe:

py2exe является расширением Python Distutils, которое преобразовывает сценарии Python в исполняемые Windows-программы, которые в состоянии работать, не требуя установки Python.

48
задан Løiten 10 April 2018 в 11:12
поделиться

5 ответов

Вы можете сделать это в однострочном режиме, используя генераторы:

next(i for i,v in enumerate(l) if is_odd(v))

Хорошая особенность генераторов в том, что они вычисляют только до запрошенного количества. Таким образом, запрос первых двух индексов (почти) столь же прост:

y = (i for i,v in enumerate(l) if is_odd(v))
x1 = next(y)
x2 = next(y)

Однако следует ожидать исключения StopIteration после последнего индекса (именно так работают генераторы). Это также удобно в вашем подходе «сначала взять», чтобы знать, что такое значение не было найдено - функция list.index () выдаст здесь ValueError.

86
ответ дан 7 November 2019 в 12:17
поделиться

Не одна функция, но вы можете сделать это довольно легко:

>>> test = lambda c: c == 'x'
>>> data = ['a', 'b', 'c', 'x', 'y', 'z', 'x']
>>> map(test, data).index(True)
3
>>>

Если вы не хотите оценивать весь список сразу, вы можете использовать itertools, но это не так красиво:

>>> from itertools import imap, ifilter
>>> from operator import itemgetter
>>> test = lambda c: c == 'x'
>>> data = ['a', 'b', 'c', 'x', 'y', 'z']
>>> ifilter(itemgetter(1), enumerate(imap(test, data))).next()[0]
3
>>> 

Простое использование выражения генератора, вероятно, более читабельно, чем itertools .

Примечание в Python3, map и filter возвращают ленивые итераторы, и вы можете просто используйте:

from operator import itemgetter
test = lambda c: c == 'x'
data = ['a', 'b', 'c', 'x', 'y', 'z']
next(filter(itemgetter(1), enumerate(map(test, data))))[0]  # 3
4
ответ дан 7 November 2019 в 12:17
поделиться

Одним из возможных вариантов является встроенная функция enumerate :

def index_of_first(lst, pred):
    for i,v in enumerate(lst):
        if pred(v):
            return i
    return None

Обычно функция, подобная той, которую вы описываете, называется «предикатом»; он возвращает истину или ложь для некоторого вопроса. Вот почему в моем примере я называю это pred .

Я также думаю, что было бы лучше вернуть None , поскольку это реальный ответ на вопрос. При необходимости вызывающий абонент может выбрать взрыв на Нет .

11
ответ дан 7 November 2019 в 12:17
поделиться

вы могли бы сделать это с пониманием списка:

l = [8,10,4,5,7]
filterl = [a for a in l if a % 2 != 0]

Тогда filterl вернет все элементы списка, удовлетворяющие выражению a% 2! = 0. Я бы сказал более элегантный метод. ..

2
ответ дан 7 November 2019 в 12:17
поделиться

@ Принятый ответ Пола лучше всего, но вот небольшой вариант для размышлений, в основном для развлечения и обучения ...:

>>> class X(object):
...   def __init__(self, pred): self.pred = pred
...   def __eq__(self, other): return self.pred(other)
... 
>>> l = [8,10,4,5,7]
>>> def is_odd(x): return x % 2 != 0
... 
>>> l.index(X(is_odd))
3

по сути, X 's цель состоит в том, чтобы изменить значение слова «равенство» с нормального на «удовлетворяет этому предикату», тем самым позволяя использовать предикаты во всех видах ситуаций, которые определены как проверка на равенство - например, это также позволит вам кодировать , вместо , если есть (is_odd (x) для x в l): , тем короче , если X (is_odd) в l: и т. д.

Стоит использовать? Не тогда, когда более явный подход, подобный принятому @Paul, так же удобен (особенно когда он изменен на использование новой блестящей встроенной функции next , а не более старой, менее подходящей .next метод, как я предлагаю в комментарии к этому ответу), но есть и другие ситуации, когда это (или другие варианты идеи «настроить значение равенства» и, возможно, другие компараторы и / или хеширование) могут быть подходящими. В основном, об этой идее стоит знать, чтобы однажды не изобретать ее с нуля; -).

12
ответ дан 7 November 2019 в 12:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: