【问题标题】:Concise way of taking N items from a lazy generator in python3? [duplicate]从python3中的惰性生成器中获取N个项目的简洁方法? [复制]
【发布时间】:2017-12-06 21:43:50
【问题描述】:

我有一个惰性生成器,我想取出 N 个项目并将它们放在一个列表中。是否有任何简洁的方式(类似于列表理解风格)而不使用 for 循环并手动将每个项目附加到列表中?

我的问题与提出的重复问题不同,因为它涉及生成器(并且您不能对生成器进行切片)并且必须满足一个条件。

这就是我现在正在做的事情:

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

【问题讨论】:

  • 由于项目添加的条件,对我来说有所不同。
  • 我有一个生成器,而不是一个列表作为输入
  • @Chris_Rands 不是您的链接的副本,这要求通过 条件函数 过滤,只采用第一个 匹配 b> n

标签: python generator


【解决方案1】:

可能有点难看,但使用列表推导从生成器中获取 n 个项目,然后过滤外部列表推导并递归

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]

我想尝试递归,但非递归可能更快:

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

【讨论】:

    【解决方案2】:

    使用itertools.islice()函数的短解:

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

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

    【讨论】:

      猜你喜欢
      • 2021-09-13
      • 1970-01-01
      • 2011-01-28
      • 1970-01-01
      • 2023-01-12
      • 1970-01-01
      • 2011-01-09
      相关资源
      最近更新 更多