【问题标题】:Python - Regularize a multidimensional jagged listPython - 正则化多维锯齿状列表
【发布时间】:2021-10-11 17:01:08
【问题描述】:

假设我在 Python 中有一个 3D 列表,但它严重锯齿状:

old_list = [[[0, 1, 2], 
             [3, 4, 5, 6], 
             [7, 8]], 
            [[9, 10], 
             [11, 12, 13, 14, 15], 
             [16, 17, 18], 
             [19, 20, 21, 22]], 
            [[23, 24, 25], 
             [26, 27]]]

我需要“规范化”它,使其仍然具有相同的元素,但使用0 来填充锯齿状部分中的任何间隙。我的目标是这样的,即 3x4x5:

new_list = [[[0, 1, 2, 0, 0], 
             [3, 4, 5, 6, 0], 
             [7, 8, 0, 0, 0], 
             [0, 0, 0, 0, 0]], 
            [[9, 10, 0, 0, 0], 
             [11, 12, 13, 14, 15], 
             [16, 17, 18, 0, 0], 
             [19, 20, 21, 22, 0]], 
            [[23, 24, 25, 0, 0], 
             [26, 27, 0, 0, 0], 
             [0, 0, 0, 0, 0], 
             [0, 0, 0, 0, 0]]]

对于任何个维度,是否有有效的算法来执行此操作?更好的是,无需导入任何东西?

更新 1:

我得到的答案还不错,但对于我的目的来说还不够好。对不起。但是我刚刚找到了解决问题的方法!不过,我需要做更多的编码。感谢您的回答!

更新 2:

BINGO! 无需再回答 - 我明白了。

【问题讨论】:

标签: python list multidimensional-array


【解决方案1】:

这个函数应该可以解决问题:

def regularize3D(list3d, padding=0):
    # figure out how long each 1d list needs to be
    target_length = max(max(len(list1d) for list1d in list2d) for list2d in list3d)
    # now remake each sublist with the right length
    return [[list1d + [padding] * (target_length-len(list1d)) for list1d in list2d] for list2d in list3d]

# Usage example
old_list = [[[0, 1, 2],
             [3, 4, 5, 6],
             [7, 8]],
            [[9, 10],
             [11, 12, 13, 14, 15],
             [16, 17, 18],
             [19, 20, 21, 22]],
            [[23, 24, 25],
             [26, 27]]]
new_list = regularize3D(old_list)
print(new_list)

# lists are mutable
# visual "unit test" ensure modifying old list does not modify new list
old_list[0][0][0] = 90000
print(new_list) # 90000 not visible at (0,0,0), test passed

【讨论】:

  • @ntg 输出为[[[1, 0, 0]], [[2, 3, 4], [5, 6, 0]]]
  • 我希望输出为 [[[1, 0, 0],[0, 0, 0],], [[2, 3, 4], [5, 6, 0]]] 虽然
【解决方案2】:

这是我制作的一个函数,它将 3D 数组中的任何 2D 数组转换为最小的 n × n 数组,用 0 填充缺失的点:

def reform(old_list):
  for twoD in old_list:
    length = len(twoD)
    maxWidth = 0
    for oneD in twoD:
      if maxWidth < len(oneD):
        maxWidth = len(oneD)
    dimensions = max(maxWidth,length)
    for oneD in twoD:
      while dimensions != len(oneD):
        oneD.append(0)
    while len(twoD) != dimensions:
      newRow = []
      for i in range(dimensions):
        newRow.append(0)
      twoD.append(newRow)
  return old_list

然后,我们可以通过以下方式打印出结果:

for twoD in new_list:
  for oneD in twoD:
    print(oneD)
  print()

如果我们的 old_list 被定义为:

old_list = [[[0, 1, 2], 
             [3, 4, 5, 6], 
             [7, 8]], 
            [[9, 10], 
             [11, 12, 13, 14, 15], 
             [16, 17, 18], 
             [19, 20, 21, 22]], 
            [[23, 24, 25], 
             [26, 27]]]

以下输出将是:

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

[9, 10, 0, 0, 0]
[11, 12, 13, 14, 15]
[16, 17, 18, 0, 0]
[19, 20, 21, 22, 0]
[0, 0, 0, 0, 0]

[23, 24, 25]
[26, 27, 0]
[0, 0, 0]

【讨论】:

  • @Rudra 这回答了你的问题还是你还需要什么?
【解决方案3】:

在我看来,关闭问题的答案主要是关于 2D 数组,如果不是,请发表评论。其中一些在测量效率方面比这里提供的更完整,但仍然可能是有效的(请注意,如果我们牺牲了一些“pythonicalization”,max_size_z 和 max_size_y 可以在一个 for 循环中完成)

max_size_z = max([len(item) for sublist in old_list for item in sublist])
max_size_y = max([len(sublist) for sublist in old_list ])
new_array = np.zeros ((len(old_list),max_size_y,max_size_z),dtype=int) # efficient mem allocation "should" make this fast
for new_sublist,old_sublist in zip(new_array,old_list):
    for new_item,old_item in zip(new_sublist,old_sublist):
        new_item[:len(old_item)] = old_item

【讨论】:

  • 我希望它适用于任何尺寸。也许有一个递归函数?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-13
  • 1970-01-01
  • 2016-07-09
  • 1970-01-01
  • 2020-04-04
相关资源
最近更新 更多