【问题标题】:Python generator that returns group of items返回一组项目的 Python 生成器
【发布时间】:2017-09-16 05:18:27
【问题描述】:

我正在尝试制作一个生成器,它可以返回列表中的多个连续项目,该列表仅“移动”一个索引。类似于 DSP 中的移动平均滤波器。例如,如果我有列表:

l = [1,2,3,4,5,6,7,8,9]

我希望这个输出:

[(1,2,3),(2,3,4),(3,4,5),(4,5,6),(5,6,7),(6,7,8),(7,8,9)]

我已经编写了代码,但它不适用于过滤器和生成器等。如果我需要提供大量单词,恐怕它也会因内存而中断。

函数gen

def gen(enumobj, n):
    for idx,val in enumerate(enumobj):
        try:
            yield tuple(enumobj[i] for i in range(idx, idx + n))
        except:
            break

以及示例代码:

words = ['aaa','bb','c','dddddd','eeee','ff','g','h','iiiii','jjj','kk','lll','m','m','ooo']
w = filter(lambda x: len(x) > 1, words)

# It's working with list
print('\nList:')
g = gen(words, 4)
for i in g: print(i)

# It's not working with filetrs / generators etc.
print('\nFilter:')
g = gen(w, 4)
for i in g: print(i)

的列表不会产生任何东西。代码应该中断,因为无法索引过滤器对象。当然,其中一个答案是强制列出:list(w)。但是,我正在为该函数寻找更好的代码。如何更改它以便函数也可以接受过滤器等。我担心列表中大量数据的内存。

谢谢

【问题讨论】:

    标签: python-3.x generator


    【解决方案1】:

    使用迭代器,您需要跟踪已读取的值。 n 大小的列表可以解决问题。将下一个值附加到列表中,并在每次产量后丢弃最上面的项目。

    import itertools
    
    def gen(enumobj, n):
        # we need an iterator for the `next` call below. this creates
        # an iterator from an iterable such as a list, but leaves
        # iterators alone.
        enumobj = iter(enumobj)
        # cache the first n objects (fewer if iterator is exhausted)
        cache = list(itertools.islice(enumobj, n))
        # while we still have something in the cache...
        while cache:
            yield cache
            # drop stale item
            cache.pop(0)
            # try to get one new item, stopping when iterator is done
            try:
                cache.append(next(enumobj))
            except StopIteration:
                # pass to emit progressively smaller units
                #pass
                # break to stop when fewer than `n` items remain
                break
    
    words = ['aaa','bb','c','dddddd','eeee','ff','g','h','iiiii','jjj','kk','lll','m','m','ooo']
    w = filter(lambda x: len(x) > 1, words)
    
    # It's working with list
    print('\nList:')
    g = gen(words, 4)
    for i in g: print(i)
    
    # now it works with iterators
    print('\nFilter:')
    g = gen(w, 4)
    for i in g: print(i)
    

    【讨论】:

    • 嗨。我需要问几件事。我是否正确地说前两行是初始化生成器并仅在生成器开始工作时运行?看起来 iterable 需要他们第一次切片对象。在while data: 行检查了什么样的条件,为什么是data?对我来说,该函数通过 yield data 返回值,它在此暂停,然后代码返回以在下一行继续。那是对的吗?抱歉,我是制作发电机的新手。谢谢
    • 我已将pass 更改为break。否则,您的函数将返回长度为 n-1、n-2、..、1 的额外项目。
    • 如果迭代器开始的项目少于n,这也可能是个问题。您可以在islice 之后添加支票并立即返回。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 2017-04-29
    • 1970-01-01
    相关资源
    最近更新 更多