Стоп цикл с пониманием списка, когда найти первый True - PullRequest
0 голосов
/ 10 ноября 2019

Я хочу остановить итерацию, когда найду первый True, например:

>> for x in ['a', 'b', 1, 2, 3]:
>>    if isinstance(x, int):
>>        print(x)
>>        break

 1

Как я могу сделать то же самое, но с пониманием списка для цикла?

Ответы [ 2 ]

3 голосов
/ 10 ноября 2019

К сожалению, нет встроенного механизма для поиска первого элемента списка, который соответствует предикату. Существует any, который можно использовать для определения , если такой элемент существует, но он не скажет вам, каким он был.

any(isinstance(x, int) for x in ['a', 'b', 1, 2, 3])

К счастью, itertools предоставляет множество функций, когда вы хотите выполнить какую-либо операцию со списком или любую другую итерацию.

Функция, которую вы ищете, не построенав модуле, но документация предоставляет определения для нескольких функций, включая эту, как рецепты itertools . Вам нужна функция с именем first_true. Просто скопируйте определение и:

def first_true(iterabe, default=False, pred=None):
    return next(filter(pred, iterable), default)

x = first_true(['a', 'b', 1, 2, 3], pred=int.__instancecheck__)

Если в списке ничего не соответствует предикату, first_true вернет False. Если вы хотите другое поведение, вы можете изменить функцию. Другие рецепты могут быть хорошим началом, если вы хотите понять, как работать с итераторами в стиле itertools.


Если вы пытаетесь выполнить более сложную обработку в цикле, чем просто найтипервый подходящий элемент, вам, вероятно, лучше использовать правильный цикл for. Постижения списков и выражения генераторов хороши в качестве замены для map и filter, а itertools предоставляет более общие операции над итерируемыми объектами, но они не предназначены для замены реальной логики цикла.

1 голос
/ 10 ноября 2019

Вы можете использовать next в выражении генератора для возврата первого True экземпляра:

x = next((a for a in ['a', 'b', 1, 2, 3] if isinstance(a, int)), None)
print(x)
1

x = next((a for a in ['a', 'b'] if isinstance(a, int)), None)
print(x)
None

Где второй аргумент является возвращаемым значением, которое позволяет избежать StopIteration ошибок

Edit (credit @martineau)

Это можно уменьшить до оператора filter, как показано в приведенном выше рецепте itertools:

x = next(filter(int.__instancecheck__, ['a', 'b', 1, 2, 3]), None)
...