1

What is the best way to skip entries in a generator expression that are created using a function and another generator?

In essence, I am looking for an expression that looks like this:

some_iter = (some_function(_x, _y, **kwargs) or continue for _x, _y in some_generator(*x))

(but the continue statement obviously doesn't work in this context)

Functionally, it should act like this:

def some_iter(*x):
    for _x, _y in some_generator(*x):
        x = some_function(_x, _y, **kwargs)
        if x:
            yield x
omegamanda
  • 388
  • 3
  • 7
  • 3
    You have to use nested generator: `(_x for _x in (function(_x) for _x in generator(*x)) if _x)` or `filter(None, (function(_x) for _x in generator(*x))` – Artemij Rodionov Sep 24 '18 at 20:52
  • Possible duplicate of [Advanced Nested List Comprehension Syntax](https://stackoverflow.com/questions/3766711/advanced-nested-list-comprehension-syntax) – agtoever Sep 24 '18 at 20:56
  • 1
    In python3.8, you can use assignment expressions `(y := function(_x) for _x in generator(*x) if y)` (I think) – cs95 Sep 24 '18 at 20:56
  • By the way, why not using the function-style generator? It works perfectly fine and is more readable. – Olivier Melançon Sep 24 '18 at 21:21
  • I might end up using the function-style generator, but the purpose of the question was to query if there was a way using the generator expression that I might not know of. If only @coldspeed's answer would work with older versions of python! – omegamanda Sep 24 '18 at 21:50

1 Answers1

1

A list comprehension allows to filter and then map. You want to manually map your function first.

gen = (x for x in map(function, generator(*args)) if x)

The above is for a generator that yields single arguments. You can use itertools.starmap if it returns a tuple of arguments.

from itertools import starmap

gen = (x for x in starmap(function, generator(*args)) if x)

Finally, if you also need to pass in keyword arguments, you will need to rely on a lambda function.

gen = (x for x in map(lambda args: function(*args, **kwargs), generator(*g_args)) if x)

Although, note that at that point, the function-style generator might be more readable.

def gen(*x):
    for args in generator(*x):
        x = some_function(*args, **kwargs)
        if x:
            yield x
Olivier Melançon
  • 21,584
  • 4
  • 41
  • 73