Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

python

list

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?

like image 378
skuzzy Avatar asked Mar 10 '15 16:03

skuzzy


People also ask

Is it faster to iterate through list or set Python?

We know how in python, set can be iterate faster than list. What's the reason behind it? Set is implemented by a hash-table data structure. For this reason, checking if a specific value exists in the set, is instant O(1) time, requires no iteration.

How do you iterate a function over a list?

We can iterate through a list by using the range() function and passing the length of the list. It will return the index from 0 till the end of the list.

Can a for loop be used to iterate over a list?

By using this for loop syntax you can iterate any sequence objects ( string , list , tuple , set , range , or dictionary(dict) ). A list contains a collection of values so, we can iterate each value present in the list using Python for loop or while loop.


3 Answers

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)))
like image 194
Padraic Cunningham Avatar answered Nov 15 '22 05:11

Padraic Cunningham


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
like image 28
vaultah Avatar answered Nov 15 '22 05:11

vaultah


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
like image 25
Alex Avatar answered Nov 15 '22 04:11

Alex