skuzzy
skuzzy

Reputation: 541

What is the most pythonic way to iterate over a list until a condition is met?

I have a list of real values:

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

I want to have the number of items iterated over, until some condition was met. For example, if the condition was item > 5, the result would be 3.

The easiest way, and perhaps most straight-forward way to do this would be:

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

Is there any other way more pythonic, preferably one-liner, which does this?

Upvotes: 8

Views: 12832

Answers (4)

vaultah
vaultah

Reputation: 46533

Your code is equivalent to the following generator expression

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

next(gen ) will return the index of the first matching element

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

or raise StopIteration (if there are no such elements) - if this is a problem consider adding some default value e.g None:

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

or using itertools.takewhile with sum (please note that you'll need to negate the predicate):

In [4]: import itertools

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

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

Upvotes: 6

Jos&#233; Ricardo Pla
Jos&#233; Ricardo Pla

Reputation: 1043

The most pythonic way to do this is with a comprehension list.

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

Upvotes: -1

Alex
Alex

Reputation: 19104

For lists, Padraic's answer! Using NumPy is definitely fastest if data structure is already an array...

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

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

Upvotes: 1

Padraic Cunningham
Padraic Cunningham

Reputation: 180411

You can use itertools.takewhile with sum which will take elements until the condition is met, using a generator expression we lazily evaluate:

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)))

Upvotes: 18

Related Questions