Python 如何在两个方向(向前、向后)获取每个元素的值的滑动窗口?
我有一个这样的价值清单Python 如何在两个方向(向前、向后)获取每个元素的值的滑动窗口?,python,python-3.x,Python,Python 3.x,我有一个这样的价值清单 lst = [1, 2, 3, 4, 5, 6, 7, 8] 所需输出: 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
lst = [1, 2, 3, 4, 5, 6, 7, 8]
所需输出:
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]
假设窗口大小为4,现在是我想要的输出:
对于列表中的每个_元素,我希望前面有4个值,后面有4个值,忽略当前值
我能够使用它来获得滑动窗口的值,但这也没有给我正确的所需输出
import more_itertools
list(more_itertools.windowed([1, 2, 3, 4, 5, 6, 7, 8], n=3))
我想这就是我的窍门。这是我写的快速代码
lst = [1, 2, 3, 4, 5, 6, 7, 8]
sliding_window_size = 3
def get_sliding_list(l, index):
l_list = []
r_list = []
min_range = 0
if index > sliding_window_size:
min_range = index - sliding_window_size
max_range = len(l)
if index + sliding_window_size < len(l):
max_range = index + sliding_window_size + 1
return (l[min_range:index], l[index + 1:max_range])
print(get_sliding_list(lst, 0))
print(get_sliding_list(lst, 1))
print(get_sliding_list(lst, 2))
print(get_sliding_list(lst, 3))
print(get_sliding_list(lst, 4))
print(get_sliding_list(lst, 5))
print(get_sliding_list(lst, 6))
print(get_sliding_list(lst, 7))
传递要检索其滑动窗口的元素的索引
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])
[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]
print(dict([(e, (lst[i+1:i+4], lst[max(i-3,0):i])) for i,e in enumerate(last)]))
{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])}
一行:
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])
[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]
print(dict([(e, (lst[i+1:i+4], lst[max(i-3,0):i])) for i,e in enumerate(last)]))
{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])}
输出:
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])
[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]
print(dict([(e, (lst[i+1:i+4], lst[max(i-3,0):i])) for i,e in enumerate(last)]))
{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])}
信用:多亏@FeRD和@Androbin的建议,解决方案现在看起来更好了您的滑动窗口让我想起了另一种数据结构:固定大小的堆栈。如果你仔细想想,你想要的实际上是一个由7个元素组成的固定大小的堆栈,其中右三个是前向窗口元素,后三个是后向窗口元素。第四个元素是当前元素。我会这样做:
import collections
my_list = [1, 2, 3, 4, 5, 6, 7, 8]
window = collections.deque([], 7)
for i in my_list:
window.append(i)
# Get the back three elements
forward_window = list(window)[-3:]
# Get the front three elements
backward_window = list(window)[:len(window)-4]
print()
print(list(forward_window))
print(list(backward_window))
当然,代码并不完全是您想要的,因为堆栈需要使用一些起始元素进行初始化,但这可以通过更多的工作来完成:
导入集合
我的清单=[1,2,3,4,5,6,7,8]
#从前三个元素开始
window=collections.deque(我的列表[:3],7)
#从第四个元素开始迭代
因为我在我的清单中[3:]:
window.append(一)
前进窗口=列表(窗口)[-3:]
后退窗口=列表(窗口)[:len(窗口)-4]
打印()
打印(列表(前进窗口))
打印(列表(后退窗口))
之后,只需通过添加一些空元素来清除堆栈:
while len(window) != 4:
window.popleft()
forward_window = list(window)[4:]
backward_window = list(window)[:3]
print()
print(list(forward_window))
print(list(backward_window))
这应该让你开始:
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)
我还建议添加一些检查,看看索引和窗口大小是否合理
如果您使用的旧Python版本还没有数据类,那么可以改用。下面是一段基于
列表理解的简洁代码
forward = [lst[i+1:i+1+window] for i in range(len(lst)]
backward = [lst[::-1][i+1:i+1+window] for i in range(len(lst)] # first reverse the input list and do same as did in forward
out = zip(forward,backward[::-1]) # first reverse the backward list and zip two list into one
输出
>>> forward
[[2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7, 8], [7, 8], [8], []]
>>> backward
[[7, 6, 5], [6, 5, 4], [5, 4, 3], [4, 3, 2], [3, 2, 1], [2, 1], [1], []]
>>> out
[([2, 3, 4], []), ([3, 4, 5], [1]), ([4, 5, 6], [2, 1]), ([5, 6, 7], [3, 2, 1]), ([6, 7, 8], [4, 3, 2]), ([7, 8], [5, 4, 3]), ([8], [6, 5, 4]), ([], [7, 6, 5])]
如果您调整窗口大小,这将适用于“更多”itertools.windowed
。由于需要7个项目(3个向后、1个当前、3个向前),因此将窗口大小设置为7
from itertools import chain
from more_itertools import windowed
n = 3
iterable = [1, 2, 3, 4, 5, 6, 7, 8]
# pad the iterable so you start with an empty backward window
it = chain([None] * n, iterable, [None] * n)
for window in windowed(it, n * 2 + 1):
print(window[n])
print('forward =', [x for x in window[n + 1:] if x is not None])
print('backward =', [x for x in window[:n] if x is not None])
输出为:
1
forward = [2, 3, 4]
backward = []
2
forward = [3, 4, 5]
backward = [1]
3
forward = [4, 5, 6]
backward = [1, 2]
4
forward = [5, 6, 7]
backward = [1, 2, 3]
5
forward = [6, 7, 8]
backward = [2, 3, 4]
6
forward = [7, 8]
backward = [3, 4, 5]
7
forward = [8]
backward = [4, 5, 6]
8
forward = []
backward = [5, 6, 7]
您可以使用“最小”和“最大”来确保您保持在列表中(不需要循环) 输出:
Forward = [4, 5, 6]
Backward = [1, 2]
反转列表?@MoonCheesez对于列表中的第一个元素
0
,前面只有4个值,但后面没有值,因为它是第一个值。你能举一个例子来说明你的意思吗?如果你加上期望值,这将很有帮助output@anuragal我已经用期望的输出更新了问题。它没有给出正确的输出。我已经用所需的输出更新了问题。对于八元素,它返回的是([6,7,8])
,这不是必需的。你能查一下吗。假设它返回([5,6,7],])
而忽略当前元素8
8元素有索引7,因此对于第8元素调用print(获取滑动列表(lst,7))
,如果使用零索引,在这种情况下,如果我<0测试:print.pprint(dict([(e),(lst[I-3:I],lst),我就不能解决前3项的向后窗口问题,除非我没有这个,第二项和第三项)[i+1:i+4]))因为i,e在枚举(lst)])
我也面临同样的问题,无法摆脱i@AnuragWagh尝试max(向后,0)如果您对变量进行注释,最好给它们更详细的名称,而不是给出详细解释的好答案