如何从列表列表中选择元素的滑动窗口?
Posted
技术标签:
【中文标题】如何从列表列表中选择元素的滑动窗口?【英文标题】:How to select a sliding window of elements from a list of lists? 【发布时间】:2019-09-30 07:06:33 【问题描述】:假设我有以下列表:
x = [[1,2,3],[4,5,6],[7,8,9,10]]
我希望选择所有大小的“窗口”,例如n=4
,错开距离,例如d=2
:
[[1,2,3],[4]] # Starts at position `0`
[[3],[4,5,6]] # Starts at position `d`
[[5,6],[7,8]] # Starts at position `2d`
[[7,8,9,10]] # Starts at position `3d`
即我希望在窗口与子列表重叠的地方采用相交的“切片”。
我该怎么做呢?
【问题讨论】:
numpy.org/doc/stable/reference/generated/… 【参考方案1】:我会选择嵌套的 for
循环,虽然它并不漂亮:
x = [[1,2,3],[4,5,6],[7,8,9,10]]
def window(x, n, offset):
pos = 0
res = []
for l in x:
# Skip `l` if offset is larger than its length
if len(l) + pos <= offset:
pos += len(l)
continue
# Stop iterating when window is complete
elif pos >= n + offset:
break
tmp = []
for el in l:
#if `el` is in window, append it to `tmp`
if offset <= pos < n + offset:
tmp.append(el)
# Stop iterating when window is complete
elif pos >= n + offset:
break
pos += 1
res.append(tmp)
return res
def flat_len(x):
"""Return length of flattened list."""
return sum(len(sublist) for sublist in x)
n = 4
d = 2
for i in range(0, flat_len(x) - n + 1, d):
print(window(x, n, i))
【讨论】:
【参考方案2】:另一种方法是实际使用平面列表,获取正确的窗口,然后再修复它。 我屈服了,最后使用了一点 numpy,使修复更容易。
x = [[1,2,3],[4,5,6],[7,8,9,10]]
from itertools import chain
import numpy as np
n = 4
d = 2
def custom_slider(x, n, d):
x_shape = [len(l) for l in x]
x_cumsum_shape = np.cumsum(x_shape) #this will come in handy for fixing slices later
x_flat = list(chain.from_iterable(x))
result = []
for i in range(0, len(x_flat) - n + 1, d):
#essentially get slice points, using the current index i to start. ignore negative or zero slices
split_pts = (x_cumsum_shape - i)[x_cumsum_shape - i > 0]
#[i: i + n] gives the correct slice. use split points to correctly mimic original arrays
temp = [list(item) for item in np.split(x_flat[i: i + n], split_pts) if item.size]
result.append(temp) #could also turn function into generator by yielding instead
return result
custom_slider(x, n, d)
输出:
[[[1, 2, 3], [4]], [[3], [4, 5, 6]], [[5, 6], [7, 8]], [[7, 8, 9, 10]]]
【讨论】:
【参考方案3】:如果您预先计算一些索引,您可以使用虚拟单线重建任何窗口:
import itertools
import operator
def window(x, start, stop):
first = indices[start][0]
last = indices[stop-1][0]
return [
[x[i][j] for i, j in g] if k in (first, last) else x[k]
for k, g in itertools.groupby(
indices[start:stop],
key=operator.itemgetter(0))
]
def flat_len(x):
"""Return length of flattened list."""
return sum(len(sublist) for sublist in x)
n=4; d=2
x = [[1,2,3],[4,5,6],[7,8,9,10]]
indices = [(i, j) for i, sublist in enumerate(x) for j in range(len(sublist))]
for i in range(0,flat_len(x)-n+1,d):
print(window(x,i,i+n,indices))
>>> [[1, 2, 3], [4]]
>>> [[3], [4, 5, 6]]
>>> [[5, 6], [7, 8]]
【讨论】:
以上是关于如何从列表列表中选择元素的滑动窗口?的主要内容,如果未能解决你的问题,请参考以下文章