代码之家  ›  专栏  ›  技术社区  ›  iacob

如何从列表中选择元素的滑动窗口?

  •  2
  • iacob  · 技术社区  · 5 年前

    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`
    

    也就是说,我希望在窗口与子列表重叠的地方取相交的“切片”。

    我该怎么办?

    2 回复  |  直到 5 年前
        1
  •  4
  •   iacob    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]]
    
        2
  •  2
  •   Paritosh Singh    5 年前

    我屈服了,在最后用了一个小屁股,使修复更容易。

    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
  •  2
  •   iacob    5 年前

    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))