2

I have found myself frequently iterating over a subset of a list according to some condition that is only needed for that loop, and would like to know if there is a more efficient way to write this.

Take for example the list:

foo = [1, 2, 3, 4, 5]

If I wanted to build a for loop that iterates through every element greater than 2, I would typically do something like this:

for x in [y for y in foo if y > 2]:
    # Do something

However this seems redundant, and isn't extremely readable in my opinion. I don't think it is particularly inefficient, especially when using a generator instead as @iota pointed out below, however I would much rather be able to write something like:

for x in foo if x > 2:
    # Do something

Ideally avoiding the need for a second for and a whole other temporary variable. Is there a syntax for this? I use Python3 but I assume any such syntax would likely have a Python2 variant as well.

Note: This is obviously a very simple example that could be better handled by something like range() or sorting & slicing, so assume foo is any arbitrary list that must be filtered by any arbitrary condition

Eric
  • 189
  • 2
  • 12
  • list comprehensions are for creating lists, not iterating lists so `[y for y in foo if y > 2]` does exactly that, create a list. You then iterate over it as a second step. – JonSG May 06 '21 at 00:42

3 Answers3

2

Not quite the syntax you are after but you can also use filter using a lambda:

for x in filter(lambda y: y > 2, foo):
    print(x)

Or using a function for readbility sake:

def greaterthantwo(y):
    return y > 2

for x in filter(greaterthantwo, foo):
    print(x)

filter also has the advantage of creating a generator expression so it doesn't evaluate all the values if you exit the loop early (as opposed to using a new list)

salparadise
  • 5,699
  • 1
  • 26
  • 32
  • This is a strong option - already far more readable, and the ability to plug in a outside function as a filter is a plus. – Eric May 06 '21 at 00:44
1

There's filter as discussed in @salparadise but you can also use generators:

def filterbyvalue(seq, value):
   for el in seq:
       if el.attribute==value: 
           yield el
           
for x in filterbyvalue(foo,2):
    #Do something

It may look bigger but it is useful when you have to do something complex instead of filtering, it is also performes better than first creating a list comprehension and then looping over it.

kinshukdua
  • 1,944
  • 1
  • 5
  • 15
0

I would do like this

For efficient code

data = (x for x in foo if x>2)
print(next(data))

For more readable code

[print(x) for x in foo if x>2]
  • List comprehensions should not be used to generate side effects : https://stackoverflow.com/questions/5753597/is-it-pythonic-to-use-list-comprehensions-for-just-side-effects – JonSG May 06 '21 at 00:47