2015-03-10 2 views
2

У меня есть список действительных значений:Каков самый pythonic способ перебора списка до тех пор, пока не будет выполнено условие?

values = [0.1, 2.9, 1.4, 5.7, 9.2, 3.8] 

Я хочу, чтобы количество элементов итерации, пока некоторое условие не было выполнено. Например, если условие было item > 5, результат будет 3.

Самый простой способ, и, возможно, самый прямой способ сделать это было бы:

for index, item in enumerate(values): 
    if (item > 5): 
     print(index) 
     break 

Есть ли другой способ более pythonic, предпочтительно однострочный, что делает это?

+5

Для чего нужен однострочный вкладыш? То, что у вас есть, совершенно понятно и делает то, что вы хотите. – arshajii

+0

Один-лайнер - это не то, что я хочу, но я не буду возражать. Вышеуказанный метод является стандартной процедурой. Мне пришло в голову, что должен быть способ сделать его более кратким, succint; аналогичные способностям распознавания списков в python. – skuzzy

ответ

9

Вы можете использовать itertools.takewhile с sum, который будет принимать элементы, пока условие не будет выполнено, используя выражение генератора мы лениво оценить:

values = [0.1, 2.9, 1.4, 5.7, 9.2, 3.8] 

from itertools import takewhile 

print(sum(1 for _ in takewhile(lambda x: x< 5,values))) 
+0

Спасибо. Не могу сказать, что код яснее, но он лаконичен и лаконичен. Что касается эффективности, однако, не будет ли много вызовов функций, если у нас действительно большой список? – skuzzy

+0

@skuzzy, вы имеете в виду скорость или память? –

+0

@Padraic Оба. Я считаю, что ленивая оценка гарантирует лучшую эффективность памяти, чем другие решения. но скорость? Наивное решение (по моему вопросу) не имеет накладных расходов на память или производительность. – skuzzy

4

Ваш код эквивалентен следующему выражению генератора

In [1]: gen = (i for i, v in enumerate(values) if v > 5) 

next(gen) будет возвращать индекс первого совпадающего элемента

In [2]: next(gen) 
Out[2]: 3 

или поднять StopIteration (если нет таких элементов) - если это проблема рассмотреть вопрос о добавлении некоторого значения по умолчанию, например None:

In [3]: next((i for i, v in enumerate(values) if v > 10), None) is None 
Out[3]: True 

или с помощью itertools.takewhile с sum (обратите внимание, что вам нужно отрицать предикат):

In [4]: import itertools 

In [5]: it = itertools.takewhile(lambda x: x <= 5, values) 

In [6]: sum(1 for _ in it) 
Out[6]: 3 
1

Для списков, ответ Padraic! Использование NumPy, безусловно, самый быстрый, если структура данных уже массив ...

In [370]: a = np.array(values) 

In [371]: (a>5).argmax() 
Out[371]: 3 
0

Самый вещий способ сделать это со списком понимания.

print next(ind for ind, i in enumerate([0.1, 2.9, 1.4, 5.7, 9.2, 3.8]) if i > 5) 
+1

Это не дает ожидаемого результата (3). – wflynny

+0

Я не хочу, чтобы общее число элементов удовлетворяло некоторому условию.Полагаю, у меня ясно, в этом вопросе. – skuzzy

+0

@wflynny thats был всего лишь образцом с понятием. Я обновляю ответ с правильным кодом на этот вопрос. –

Смежные вопросы