将带有点分隔的字符串的类型T的点列表转换为树状结构

时间:2016-10-13 18:03:46

标签: c#

我有一个T1类型的列表,其中dot作为父子的分隔符 与

[
{
Id: 1,
Name: "child1"
},
{
Id: 2,
Name: "child1.child2"
},
{
Id: 3,
Name: "child1.child2.child3"
},
{
Id: 4,
Name: "child10"
},
{
Id: 5,
Name: "child10.child11"
},
{
Id: 6,
Name: "childT.Son.Son1"
},
{
Id: 7,
Name: "childOne"
},
]

我需要将它转换为具有此格式的树状结构

public class TreeViewDto
{
    public string Label { get; set; }
    public bool Selected { get; set; }
    public int Id { get; set; }
    public List<TreeViewDto> Children { get; set; }
}

以上示例看起来像

[
{
Id: 1,
Label: "child1",
Children: [{
        Id: 2,
        Label: "child2"
        Children: [{
                        Id: 3,
                        Label: "child3"
                        }]
        },]},
{
Id: 4,
Label: "child10"
},      
    {
Id: 6,
Label: "childT.Son.Son1"
},
{
Id: 7,
Label: "childOne"
},
{
Id: 4,
Label: "child10",
Children: [{
        Id: 5,
        Label: "child11"}]
  }
]

我怎样才能实现这一目标?

2 个答案:

答案 0 :(得分:0)

一种简单的方法是逐层进行:

  • 制作名称到节点映射的平面列表
  • 对于其中没有点'.'的每个名称,将第一级节点添加到结果中;从原始列表中删除节点
  • 对于每个带有一个点的名称,查找其父级,并将该节点添加为子级;从原始列表中删除节点
  • 对具有两个点,三个点,四个点等的名称重复上述步骤
  • 可以使用辅助方法简化节点作为子节点的添加,该方法采用表示&#34;路径&#34;的字符串数组。 (您可以通过全名调用Split('.')来创建此数组。)

答案 1 :(得分:0)

你可以通过首先创建一个帮助方法来做到这一点,该方法可以通过它的标签获取节点的子节点(即:GetChildByLabel(TreeViewDto parent, string label)} 然后,您可以遍历列表并将项目添加到相应的父节点。为此,您还需要一个空的根节点来接收没有父节点的所有节点:

var root = new TreeViewDto { Children = new List<TreeViewDto>() };
foreach (var el in list) {
    var path = el.Name.Split('.');
    var parent = root;
    int last = path.Length - 1;
    for (int i = 0; i < last; i++) {
        parent = GetChildByLabel(parent, path[i]);
    }
    parent.Children.Add(new TreeViewDto {
        Label = path[last], Id = el.Id, Children = new List<TreeViewDto>()
    });
}

现在root.Children是您想要的列表。 但是,如果孩子没有父母或者先列出父母,这将不起作用。 对于后一种情况,您可以先按名称中的点数对列表进行排序:

list.Sort((el1, el2) => el1.Name.Count(c => c == '.') - el2.Name.Count(c => c == '.'));

这样父节点将始终首先出现在列表中。