Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get sliding window of a values for each element in both direction (forward, backward)?

I have a list of values like this,

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

Desired Output:

window size = 3
    1  # first element in the list
    forward = [2, 3, 4]
    backward = []

    2  # second element in the list
    forward = [3, 4, 5]
    backward = [1]

    3  # third element in the list
    forward = [4, 5, 6]
    backward = [1, 2]

    4  # fourth element in the list
    forward = [5, 6, 7]
    backward = [1, 2, 3]

    5  # fifth element in the list
    forward = [6, 7, 8]
    backward = [2, 3, 4]

    6  # sixth element in the list
    forward = [7, 8]
    backward = [3, 4, 5]

    7  # seventh element in the list
    forward = [8]
    backward = [4, 5, 6]

    8  # eight element in the list
    forward = []
    backward = [5, 6, 7]

Lets assume a window size of 4, now my desired output:

for each_element in the list, I want 4 values in-front and 4 values backward ignoring the current value.

I was able to use this to get sliding window of values but this also not giving me the correct required output.

import more_itertools
list(more_itertools.windowed([1, 2, 3, 4, 5, 6, 7, 8], n=3))
like image 592
user_12 Avatar asked Jun 11 '20 03:06

user_12


People also ask

What is the window sliding technique?

Window Sliding Technique is a computational technique which aims to reduce the use of nested loop and replace it with a single loop, thereby reducing the time complexity.

How does sliding window algorithm work?

The Sliding Window algorithm is one way programmers can move towards simplicity in their code. This algorithm is exactly as it sounds; a window is formed over some part of data, and this window can slide over the data to capture different portions of it.

What is sliding time window?

In a sliding window, tuples are grouped within a window that slides across the data stream according to a specified interval. A time-based sliding window with a length of ten seconds and a sliding interval of five seconds contains tuples that arrive within a ten-second window.


2 Answers

Code:

arr = [1, 2, 3, 4, 5, 6, 7, 8]
window = 3
for backward, current in enumerate(range(len(arr)), start = 0-window):
    if backward < 0:
        backward = 0
    print(arr[current+1:current+1+window], arr[backward:current])

Output:

[2, 3, 4], []
[3, 4, 5], [1]
[4, 5, 6], [1, 2]
[5, 6, 7], [1, 2, 3]
[6, 7, 8], [2, 3, 4]
[7, 8], [3, 4, 5]
[8], [4, 5, 6]
[], [5, 6, 7]

One Liner:

print(dict([(e, (lst[i+1:i+4], lst[max(i-3,0):i])) for i,e in enumerate(last)]))

Output:

{1: ([2, 3, 4], []),
 2: ([3, 4, 5], [1]),
 3: ([4, 5, 6], [1, 2]),
 4: ([5, 6, 7], [1, 2, 3]),
 5: ([6, 7, 8], [2, 3, 4]),
 6: ([7, 8], [3, 4, 5]),
 7: ([8], [4, 5, 6]),
 8: ([], [5, 6, 7])}

Credit: thanks to suggestions from @FeRD and @Androbin, the solution now looks better

like image 125
Anurag Wagh Avatar answered Oct 09 '22 12:10

Anurag Wagh


This should get you started:

from dataclasses import dataclass
from typing import List

@dataclass
class Window:
  index: int
  backward: List[int]
  forward: List[int]

def window(iterable, window_size, index):
  backward = iterable[max(0, index - window_size):index]
  forward = iterable[index + 1:index + 1 + window_size]
  return Window(index, backward, forward)
>>> window([1,2,3,4,5,6], 3, 0)
Window(index=0, backward=[], forward=[2, 3, 4])
>>> window([1,2,3,4,5,6], 3, 5)
Window(index=5, backward=[3, 4, 5], forward=[])

I would also suggest adding some checks whether the index and window size make sense.

If you are stuck with an older Python version that doesn't have dataclasses yet, you can use Named Tuples instead.

like image 12
Hubert Grzeskowiak Avatar answered Oct 09 '22 13:10

Hubert Grzeskowiak