使用深度值镜像列表到嵌套列表~Python

时间:2015-09-03 17:02:34

标签: python nested character

我正在自动化我的装配过程,并尝试构建C4D Python脚本。我正在尝试将基于深度值的列表镜像到嵌套列表。

假设我们有深度值列表

depth_list = [[0,'Hips'],[1,'Spine'],[2,'Spine1'],[3,'Spine2'],[4,'Neck'],[5,'Head'],[6,'HeadTop_End'],[4,'LeftShoulder']]

我们希望此根据深度值成为嵌套联合列表

joint_list = [['Hips',['Spine',['Spine1',['Spine2',['Neck',['Head',['HeadTop_End']]],['LefShoulder']]]]]]

我到目前为止:

for joint in depth_list:
    this_depth = joint[0]
    try:
        joint_list.append(0)
    except IndexError:
        pass

这是我从C4D树导出器脚本

获得的原始数据
0  Hips
1      Spine
2          Spine1
3              Spine2
4                  Neck
5                      Head
6                          HeadTop_End
4                  LeftShoulder

这是一张图片:

  

[![在此处输入图像说明] [1]] [1]

每个人都欢乐千万!

2 个答案:

答案 0 :(得分:2)

你可以递归地执行此操作,如下所示:

depth_list = [[0,'Hips'],[1,'Spine'],[2,'Spine1'],[3,'Spine2'],[4,'Neck'],[5,'Head'],[6,'HeadTop_End'],[4,'LeftShoulder']]

def construct(depth_list, current_level=0):
    output = []
    while len(depth_list) > 0:
        new_level, new_name = depth_list[0]

        if new_level == current_level:
            output.append([new_name])
            depth_list.pop(0)
        elif new_level > current_level:
            child = construct(depth_list, new_level)
            output[-1].extend(child)
        else:
            return output

  return output

print(construct(depth_list))

基本思想是递归遍历输入列表。每次遇到元素时,都会执行以下三种操作之一:

  1. 如果关节处于同一水平,则从depth_list移除关节并将其添加到输出(包含此当前级别的所有关节)。
  2. 如果关节深一层,则不要修改depth_list,而是递归以获取子树。然后,将该树添加到输出列表中的最后一个元素,即当前关节。 (递归调用还将从depth_list)中删除正确数量的元素。
  3. 如果它处于较浅的级别,请放弃并返回并让父级继续循环depth_list的剩余部分。
  4. 请注意,此功能是破坏性的 - 一旦功能完成,它将depth_list完全清空。如果要保留它,请在调用函数之前复制列表:

    copy = list(depth_list)
    print(construct(copy))
    

答案 1 :(得分:1)

您可以尝试以下代码:

depth_list = [[0,'Hips'],[1,'Spine'],[2,'Spine1'],[3,'Spine2'],[4,'Neck'],[5,'Head'],[6,'HeadTop_End'],[4,'LeftShoulder']]

result = []

current_list = None
current_item = []
current_level = 0

level_dict = {}

for depth, value in depth_list:
    if depth == 0:
        if current_list:
            result.append(current_list)
            current_list = None
        current_list = current_item
        current_item.append(value)
        level_dict[0] = current_list
    elif depth == current_level:
        current_item.append(value)
    elif depth == current_level + 1:
        append_item = []
        level_dict[depth] = current_item
        current_item.append(append_item)
        append_item.append(value)
        current_item = append_item
        current_level += 1
    else:
        level_dict[depth].append(value)

if current_list:
    result.append(current_list)

print result

这个想法是跟踪以前的水平。我还在字典上保持所有级别的安全,以便在先前检查的级别上插入项目。例如,当您在第6级项目上时,您正在等待第7级项目,但会出现第4级项目,因此您必须相应地更新列表。

<强>更新

我认为这个解决方案比另一个更清晰。它会更慢,因为它会对输入进行排序,但是如果你没有像10.000项或更多项的输入,它将不会产生很大的差异,你将获得清晰的代码。此外,这种方法总是将项目置于级别之前。此功能假定您每个级别至少提供一个项目。所以,鉴于这些事实,这是解决方案:

from itertools import groupby

depth_list = [[0, 'Hips'], [1, 'Spine'], [2, 'Spine1'], [3, 'Spine2'], [4, 'Neck'], [5, 'Head'], [6, 'HeadTop_End'], [4, 'LeftShoulder'], [5, 'LeftArm'], [6, 'LeftForeArm'], [7, 'LeftHand']]

result = []
current_level = result

get_level_number = lambda item_info: item_info[0]

sorted_by_level = sorted(depth_list, key=get_level_number)
grouped_by_level = groupby(sorted_by_level, key=get_level_number)

for level_number, grouped_items in grouped_by_level:
    level = [tag for level, tag in grouped_items]
    print level_number, level
    current_level.append(level)
    current_level = level

print result