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

如何将可变形状嵌套列表复制到固定形状列表

  •  0
  • GabrielChu  · 技术社区  · 7 年前

    基本上,我尝试对可变长度的输入进行填充。

    鉴于 以下内容:

    假设变量形状列表是

    seq = [[[1,2,3], [4,5,6,7]],
           [[1], ],
           [[7,8,9], [10,11]]]
    

    零的固定形状列表的形状为 [3, 2, 4]

    fixed_list = [[[0, 0, 0, 0], [0, 0, 0, 0]],
                  [[0, 0, 0, 0], [0, 0, 0, 0]],
                  [[0, 0, 0, 0], [0, 0, 0, 0]]]
    

    输出:

    所需的输出是从变量形状列表复制到其 固定形状列表中的相应尺寸

    output = [[[1, 2, 3, 0], [4, 5, 6, 7]],
              [[1, 0, 0, 0], [0, 0, 0, 0]],
              [[7, 8, 9, 0], [10, 11, 0, 0]]]
    

    是否有任何递归的方法来实现复制过程?

    只是一个小提示:这只是一个具体的例子,可以有更多的其他固定形状,即, [3,2,5,6,7] [3,4] 对于其他序列示例。

    编辑时间:

    序列也可以是,

    seq = [[1,4,5,7],
           [2,8],
           [6,3,2]]
    
    expected_output = [[1,4,5,7],
                       [2,8,0,0],
                       [6,3,2,0]]
    

    它的形状是 [3,4] ,填充也应该在这个上得到推广。

    编辑时间:

    这是我生成的代码 fixed_list 作为对评论的回应。

    def _dfs_max_len(seqs: list, layers: defaultdict, count=0):
        try:
            len_ = len(seqs)
            if len_ > layers[count]:
                layers[count] = len_
            count += 1
        except TypeError:
            return
    
        for i in range(len_):
            _dfs_max_len(seqs[i], layers, count)
    
    def get_seqs_shape(seqs: list):
        shape = defaultdict(int)
        _dfs_max_len(seqs, shape)
    
        return list(shape.values()) # won't need `list` for python2 
    
    def zeros_list(shape: list):
        if len(shape) == 1:
            return [0 for _ in range(shape[0])]
    
        curnt_shape = shape[0]
        sublist = zeros_list(shape[1:])
        return [sublist for _ in range(curnt_shape)]
    
    shape = get_seqs_shape(seq)
    zeros = zeros_list(shape)
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Paul Panzer    7 年前

    这里有一个半递归的解决方案,第一个实际上用零填充,第二个嵌入到现有的零块(或其他值)中。

    import itertools as it
    
    def subdims(L):
        """determine the depth and max dimensions of a nested list"""
        SL = (subdims(S) for S in L if isinstance(S, list))
        return (len(L), *map(max, it.zip_longest(*SL, fillvalue=0)))
    
    def pad(L, dims):
        """zero-pad a nested list to flush faces"""
        d, *sdims = dims
        L = it.chain(L, it.repeat(0, d-len(L))) if L else it.repeat(0, d)
        return list(map(pad, L, it.repeat(sdims)) if sdims else L)
    
    def py_zeros(dims):
        """create an nd block (a nested list) of zeros"""
        d, *sdims = dims
        return [py_zeros(sdims) if sdims else 0 for _ in range(d)]
    
    def embed(L, Z):
        """copy a nested list into another large enough nested list"""
        for i, x in enumerate(L):
            if isinstance(x, list):
                embed(x, Z[i])
            else:
                Z[i] = x
    

    演示:

    # pad directly or ...
    >>> pad(seq, subdims(seq))
    [[[1, 2, 3, 0], [4, 5, 6, 7]], [[1, 0, 0, 0], [0, 0, 0, 0]], [[7, 8, 9, 0], [10, 11, 0, 0]]]
    >>> 
    
    # ... create a block of zeros and ...
    >>> py_zeros(subdims(seq))
    >>> Z = py_zeros(subdims(seq))
    [[[0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0]]]
    
    # ... copy there
    >>> embed(seq, Z)
    >>> Z
    [[[1, 2, 3, 0], [4, 5, 6, 7]], [[1, 0, 0, 0], [0, 0, 0, 0]], [[7, 8, 9, 0], [10, 11, 0, 0]]]
    
        2
  •  0
  •   hilberts_drinking_problem    7 年前

    fixed_list shape

    seq = [[[1, 2, 3], [4, 5, 6, 7]], [[1]], [[7, 8, 9], [10, 11]]]
    
    fixed_list = [
        [[0, 0, 0, 0], [0, 0, 0, 0]],
        [[0, 0, 0, 0], [0, 0, 0, 0]],
        [[0, 0, 0, 0], [0, 0, 0, 0]],
    ]
    
    from itertools import product
    
    
    def shape(xs):
        sh = list()
        while type(xs) is list:
            sh.append(len(xs))
            xs = xs[0]
    
        return sh
    
    
    def upd(template, content):
        sh = shape(template)
        for ix in product(*map(range, sh)):
            temp = template
            con = content
    
            for i in ix[:-1]:
                try:
                    temp = temp[i]
                    con = con[i]
                except:
                    break
            else:
                temp[: len(con)] = con[:]
    
    
    upd(fixed_list, seq)