生成可迭代的滑动窗口,长度为n

时间:2017-02-09 03:28:08

标签: python

def windows(iterable,n,m=1):
    x = iter(iterable)
    l = []
    y = next(x)
    for i in range(n):
        l.append(y)
        y = next(x)
    yield l

    while x:
        for i in range(m):
            l.pop(0)
        for i in range(m):
            l.append(y)
            y = next(x)
        yield l

我需要编写一个Windows生成器,它采用一个可迭代的和两个整数(称为n和m; m的默认值为1)作为参数:它生成n个值的列表:第一个列表包含前n个值;每个后续列表都会删除前一个列表中的前m个,并从迭代中添加下一个m值,直到返回列表中的值少于n个。

例如:

for i in windows('abcdefghijk', 4,2):
    print(i,end='')

打印['a','b','c','d'] ['c','d','e','f'] ['e','f','g','h'] ['g','h','i','j']

当我调用上面的函数时,我的代码打印

[['i', 'j', 'k'], ['i', 'j', 'k'], ['i', 'j', 'k'], ['i', 'j', 'k']]

我无法弄清楚问题。有人可以帮我解决吗?提前致谢。

4 个答案:

答案 0 :(得分:1)

您应该使用切片来抓取n项,并且其起始值会增加m

def windows(iterable, n, m = 1):
    if m == 0: # otherwise infinte loop
        raise ValueError("Parameter 'm' can't be 0")
    lst = list(iterable)
    i = 0
    while i + n < len(lst):
        yield lst[i:i + n]
        i += m

# Output
>>> for i in windows('abcdefghijk', 4, 2):
    print(i)

['a', 'b', 'c', 'd']
['c', 'd', 'e', 'f']
['e', 'f', 'g', 'h']
['g', 'h', 'i', 'j']

答案 1 :(得分:1)

也许是这样的,假设你没有使用懒惰的迭代。

def windows(iterable, n, m=1):
    length = len(iterable)
    i = 0

    while i + n < length:
        yield list(iterable[i:i + n])
        i += m

for win in windows('abcdefghijk', 4, 2):
    print(win)

输出

['a', 'b', 'c', 'd']
['c', 'd', 'e', 'f']
['e', 'f', 'g', 'h']
['g', 'h', 'i', 'j']

答案 2 :(得分:0)

似乎适用于我尝试的少数情况,发电机本身就是单线

def WindGen(astr, n, m = 1):
    if m !=0:
        return (list(astr[i * m : i * m + n]) for i in range((len(astr) - n) // m + 1))    

astr = 'abcdefghijk'
n, m = 4, 2
print(*WindGen(astr, n, m), sep='\n')
['a', 'b', 'c', 'd']
['c', 'd', 'e', 'f']
['e', 'f', 'g', 'h']
['g', 'h', 'i', 'j']

答案 3 :(得分:0)

以下内容也将起作用,并且在某些情况下不会错过结尾条款:

def sliding_window(iterable, window_size, step_size=1):
    length = len(iterable)
    i = 0
    end_flag = False
    while not end_flag:
        curr_split = list(iterable[i:i + window_size])
        if len(curr_split) < window_size:
            end_flag = True
            curr_split.extend([None] * (window_size - len(curr_split)))
        yield curr_split
        i += step_size

iterable = 'abcdefghijk'
window_size = 4
step_size = 2
res = list(sliding_window(iterable, window_size, step_size))
print(res)

输出:

[['a', 'b', 'c', 'd'],
 ['c', 'd', 'e', 'f'],
 ['e', 'f', 'g', 'h'],
 ['g', 'h', 'i', 'j'],
 ['i', 'j', 'k', None]]