Tengo una lista de valores como este,
lst = [1, 2, 3, 4, 5, 6, 7, 8]Salida deseada :
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]Supongamos un tamaño de ventana de 4, ahora mi resultado deseado:
para each_element en la lista, quiero 4 valores al frente y 4 valores al revés ignorando el valor actual.
Pude usar esto para obtener una ventana deslizante de valores, pero esto tampoco me dio el resultado requerido correcto.
import more_itertools list(more_itertools.windowed([1, 2, 3, 4, 5, 6, 7, 8], n=3))[ll[i-4:i+4] for i in range(4, len(ll)-4)]hace el truco, debo pensar.
Aquí está el código rápido que escribí
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))Producción
([], [2, 3, 4]) ([1], [3, 4, 5]) ([1, 2], [4, 5, 6]) ([1, 2, 3], [5, 6, 7]) ([2, 3, 4], [6, 7, 8]) ([3, 4, 5], [7, 8]) ([4, 5, 6], [8]) ([5, 6, 7], []) Pase el index del elemento para el que desea recuperar la ventana deslizante
Código:
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])Producción:
[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]Un trazador de líneas:
print(dict([(e, (lst[i+1:i+4], lst[max(i-3,0):i])) for i,e in enumerate(last)]))Producción:
{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])}Crédito: gracias a las sugerencias de @FeRD y @Androbin, la solución ahora se ve mejor
Su ventana deslizante me recuerda a otra estructura de datos: pilas de tamaño fijo. Si lo piensa, lo que realmente quiere es una pila de tamaño fijo de 7 elementos donde los tres de la derecha son los elementos de la ventana delantera y los tres traseros son los elementos de la ventana trasera. El cuarto elemento es el elemento actual. Así es como lo haría:
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))Por supuesto, el código no es exactamente lo que desea, ya que la pila debe prepararse con algunos elementos iniciales, pero eso se puede hacer con un poco más de trabajo:
import collections my_list = [1, 2, 3, 4, 5, 6, 7, 8] # Start with the first three elements window = collections.deque(my_list[:3], 7) # Iterate from the fourth element for i in my_list[3:]: window.append(i) forward_window = list(window)[-3:] backward_window = list(window)[:len(window)-4] print() print(list(forward_window)) print(list(backward_window))Después de eso, solo necesita borrar la pila agregando algunos elementos vacíos:
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))Esto debería ayudarlo a comenzar:
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=[])También sugeriría agregar algunos controles si el índice y el tamaño de la ventana tienen sentido.
Si está atascado con una versión anterior de Python que aún no tiene clases de datos, puede usar Tuplas con nombre en su lugar.
Aquí hay un código breve y ordenado basado en list comprehension .
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 oneProducción
>>> 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])]Esto funcionará con more_itertools.windowed si ajusta el tamaño de la ventana. Dado que desea 7 elementos (3 hacia atrás, 1 actual, 3 hacia adelante), establezca el tamaño de la ventana en 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])La salida es:
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]Simplemente puede usar min y max para asegurarse de permanecer dentro de la lista (no se necesitan bucles).
lst = [1, 2, 3, 4, 5, 6, 7, 8] ws = 3 # window st = 3 # starting point mn = max(st-ws-1, 0) mx = min(st+ws, len(lst)) print('Forward = ',lst[st:mx]) print('Backward = ', lst[mn:st-1])Producción:
Forward = [4, 5, 6] Backward = [1, 2]