删除c#List中的空节点

时间:2017-02-09 08:33:40

标签: javascript c# arrays treeview bootstrap-treeview

我有一个C#对象,在JSON序列化之后变成这样:

var tree = [{
Id:1,
text: "Parent 1",
ParentId:0
nodes: [
  {
    Id:2,
    text: "Child 1",
    ParentId:1
    nodes: [
      {
        Id:3
        text: "Grandchild 1",
        ParentId:2,
        nodes:[]
      },
      {
        Id:4,
        text: "Grandchild 2",
        ParentId:2,
        nodes: []
      }
    ]
  },
  {
    Id:5
    text: "Child 2",
    ParentId:1,
    nodes: []
  }
]
},
{
Id:6,
text: "Parent 2",
ParentId:0
nodes: []
}];

我想从对象中删除所有空的节点,即[],或者只是将它们标记为null,所以我的最终对象看起来像

var tree = [{
Id:1,
text: "Parent 1",
ParentId:0
nodes: [
  {
    Id:2,
    text: "Child 1",
    ParentId:1
    nodes: [
      {
        Id:3
        text: "Grandchild 1",
        ParentId:2,
        nodes:null
      },
      {
        Id:4,
        text: "Grandchild 2",
        ParentId:2,
        nodes:null
      }
    ]
  },
  {
    Id:5
    text: "Child 2",
    ParentId:1,
    nodes:null
  }
]
},
{
Id:6,
text: "Parent 2",
ParentId:0
nodes:null
}];

列表是动态的,可以有很多分支。谢谢。 我的C#类是这个

public class Tree
{
    public int Id { get; set; }
    public string text { get; set; }
    public int ParentId { get; set; }
    public List<Tree> nodes { get; set; }
}

用于创建树列表对象我的函数:

var treeItems = new List<Tree>(); //Contails Flat Data No tree
treeItems = SomeMethod(); //To populate flat Data
treeItems.ForEach(item => item.nodes = treeItems.Where(child => child.ParentId == item.Id).ToList());

现在我在

中获取树结构
var tree = treeItems.First();

我需要一些逻辑,以便它最好使用linq将所有nodes = null放在所有嵌套级别中。 这样我就可以使用bootstrap-treeview数据源。

3 个答案:

答案 0 :(得分:1)

var treeItems = new List<Tree>(); //Contails Flat Data No tree
treeItems = SomeMethod(); //To populate flat Data
treeItems.ForEach(item => item.nodes = treeItems.Where(child => child.ParentId == item.Id).Any()?treeItems.Where(child => child.ParentId == item.Id).ToList():null);

答案 1 :(得分:0)

您只需将nodes设为null

即可
foreach (var treeItem in treeItems)
{
    if (treeItem.nodes!=null && treeItem.nodes.Count==0)
    {
        treeItem.nodes = null;                    
    }
}

编辑:为子级别递归执行:

public static class ResursiveLogic
{
    public static List<Tree> RemoveEmptyNodes(this List<Tree> tree)
    {
        if (tree==null)
        {
            return null;
        }
        if (tree.Count == 0)
        {
            return null;
        }

        foreach (var subtree in tree)
        {
            subtree.nodes = subtree.nodes.RemoveEmptyNodes();
        }
        return tree;
    }
}

如下所示:

treeItems.RemoveEmptyNodes();

这可能不是最好的解决方案,因为递归对性能不利。您应该检查JSON序列化程序是否可以通过实现自定义代码为您执行此操作。

答案 2 :(得分:0)

  class Program
{
    static void Main(string[] args)
    {
        List<Tree> treeItems = SomeMethod(); 

        Console.WriteLine("BEFORE");            
        Write(treeItems.First(), 0);

        Do(treeItems.First());

        Console.WriteLine();
        Console.WriteLine("AFTER");            
        Write(treeItems.First(), 0);

        Console.ReadKey();
    }

    private static void Write(Tree t, int currentLevel)
    {
        string space = " ".PadLeft(currentLevel);            

        Console.WriteLine($"{space}{t.Id} : {t.text} : {t.nodes?.Count.ToString() ?? "NULL"}");

        if (t.nodes == null)
            return;

        foreach (Tree tree in t.nodes)
        {                                              
            Write(tree, currentLevel + 1);
        }
    }


    private static void Do(Tree t)
    {
        foreach (Tree tree in t.nodes)
        {
            Do(tree);
        }

        if (t.nodes.Count == 0)
            t.nodes = null;                          
    }

    private static List<Tree> SomeMethod()
    {
        List<Tree> root = new List<Tree>()
        {
            new Tree() {Id = 1, text = "Root", ParentId = -1, nodes = new List<Tree>()}
        };

        root[0].nodes.Add(new Tree { Id = 4, text = "Level2A", ParentId = 2, nodes = new List<Tree>() });
        root[0].nodes.Add(new Tree { Id = 5, text = "Level2B", ParentId = 2, nodes = new List<Tree>()});

        root[0].nodes[1].nodes.Add(new Tree { Id = 6, text = "Level3A", ParentId = 5, nodes = new List<Tree>() });
        root[0].nodes[1].nodes.Add(new Tree { Id = 7, text = "Level3B", ParentId = 5, nodes = new List<Tree>() });
        root[0].nodes[1].nodes.Add(new Tree { Id = 8, text = "Level3C", ParentId = 5, nodes = new List<Tree>() });

        root[0].nodes[1].nodes[1].nodes.Add(new Tree { Id = 9, text = "Level4A", ParentId = 7, nodes = new List<Tree>() });


        root[0].nodes[1].nodes[1].nodes[0].nodes.Add(new Tree { Id = 10, text = "Level5A", ParentId = 9, nodes = new List<Tree>() });
        root[0].nodes[1].nodes[1].nodes[0].nodes.Add(new Tree { Id = 11, text = "Level5b", ParentId = 9, nodes = new List<Tree>() });

        return root;
    }

    public class Tree
    {
        public int Id { get; set; }
        public string text { get; set; }
        public int ParentId { get; set; }
        public List<Tree> nodes { get; set; }
    }
}

Output

<强>更新 如果需要迭代所有列表,不仅第一项在main函数中使用Do2(树)方法。

private static void Do2(List<Tree> t)
    {
        foreach (Tree tree in t)
        {
            if (tree.nodes.Count == 0)
                tree.nodes = null;
            else
                Do2(tree.nodes);
        }            
    }