4

I have a sequence, window size and step:

seq = [0,1,2,3,4]
n=4
step=2

from more_itertools import windowed
list(windowed([0,1,2,3,4], n, fillvalue=0, step=step))

result:

[(0, 1, 2, 3), (2, 3, 4, 0)]

but I need:

[(0, 1, 2, 3), (2, 3, 4, 0), (4, 0, 0, 0)]

Please help me find a solution

Georgy
  • 12,464
  • 7
  • 65
  • 73
hyper
  • 139
  • 10
  • 1
    @JackMoody My interpretation is that the window should slide forward by `step=2` elements in each iteration - so the first window starts at `0`, the 2nd at `2`, and the 3rd at `4`. Then the input is exhausted and no further windows are returned. – Aran-Fey Apr 09 '19 at 10:31
  • the window moves in steps of 2, (4, 0, 0, 0) is just the next window shift. No, I can not add to the manual, because this is just an example, and the window pitch and its size can be different, as well as the sequence – hyper Apr 09 '19 at 10:32
  • I see. Thanks @Aran-Fey. – Jack Moody Apr 09 '19 at 10:34
  • Once the fillvalue is used once (it is used in the second tuple), more_itertools stops. This is as should be expected. – Jack Moody Apr 09 '19 at 10:39
  • a ugly way to solve this, append 0 in tail. – recnac Apr 09 '19 at 10:41

4 Answers4

3

Just write your own windowed function:

def windowed(iterable, size, fillvalue=None, step=1):
    for i in range(0, len(iterable), step):
        window = iterable[i:i+size]
        window += [fillvalue] * (size - len(window))
        yield window
>>> list(windowed([0,1,2,3,4], 4, fillvalue=0, step=2))
[[0, 1, 2, 3], [2, 3, 4, 0], [4, 0, 0, 0]]
Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
3

How about using padded?

seq = [0,1,2,3,4]
n=4
step=2

from more_itertools import windowed, padded
list(windowed(padded(seq, 0, n=n, next_multiple=True), n, step=step))
dbramwell
  • 1,298
  • 6
  • 11
3

this should also work with iterables and not just sequences:

from itertools import islice

def sliding_window(seq, n, step, fillvalue=None):
    it = iter(seq)
    values = tuple(islice(it, n))
    while values:
        yield values + (n-len(values)) * (fillvalue, )
        values = values[step:] + tuple(islice(it, step))

the function outputs:

print(list(sliding_window(seq, n, step, fillvalue=0)))
# [(0, 1, 2, 3), (2, 3, 4, 0), (4, 0, 0, 0)]

most of it is borrowed from the original itertools recipe for a sliding window.

hiro protagonist
  • 44,693
  • 14
  • 86
  • 111
0

Consider more_itertools.stagger:

Given

import itertools as it

import more_itertools as mit


iterable = [0, 1, 2, 3, 5]

Code

Get all results from sliding windows:

windows = list(mit.stagger(iterable, offsets=(0, 1, 2, 3), longest=True, fillvalue=0))
windows
# [(0, 1, 2, 3), (1, 2, 3, 5), (2, 3, 5, 0), (3, 5, 0, 0), (5, 0, 0, 0)]

Next, filter out the desired results:

[w for i, w in enumerate(windows) if not (i % 2)]
# [(0, 1, 2, 3), (2, 3, 5, 0), (5, 0, 0, 0)]

or slice the iterable:

list(it.islice(windows, 0, None, 2))
# [(0, 1, 2, 3), (2, 3, 5, 0), (5, 0, 0, 0)]
pylang
  • 40,867
  • 14
  • 129
  • 121