0

I have a lazy generator which I want to take N items and put them in a list. Is there any concise way (Akin to list comprehension style) without using for loop and manually appending each item to a list?

My question is different than the duplicate one proposed because it involves generators (And you cannot slice generators) and has a condition which has to be satisfied.

This is what I'm doing now:

    my_list = []
    counter = 0
    for item in my_generator():
        if counter == 10:
            break           
        if condition(item):
            my_list.append(item)
            counter += 1
Warrior
  • 563
  • 1
  • 6
  • 20

2 Answers2

0

Short solution using itertools.islice() function:

my_list = list(itertools.islice(my_generator, 0, 10))

https://docs.python.org/3.6/library/itertools.html?highlight=itertools#itertools.islice

RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
0

maybe a little ugly but uses a list comprehension to grab n items from your generator, then filters in a outer list comprehension and recurses

def takeN(gen, func, n, items=list()): 
    if len(items) == n:
        return items
    return takeN(gen, func, n,
                 items + [fgen 
                          for fgen in [next(gen) for i in range(n-len(items))]
                                   if func(fgen) == True])

my_gen = (i for i in range(1,100))

takeN(my_gen, lambda x: x%3 == 0, 7)
Out[89]: [3, 6, 9, 12, 15, 18, 21]

takeN(my_gen, lambda x: x%3 == 0, 7)
Out[90]: [24, 27, 30, 33, 36, 39, 42]

takeN(my_gen, lambda x: x%2 == 0, 12)
Out[91]: [44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66]

I wanted to try recursion, but nonrecursive is likely faster:

def takeN(gen, func, n):
    items=list() 
    while len(items) != n:
        items += [fgen for fgen in [next(gen) for i in range(n-len(items))]
                                if func(fgen) == True]
    return items
f5r5e5d
  • 3,656
  • 3
  • 14
  • 18