2

我有一个 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();

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

4

3 回答 3

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);
于 2017-02-09T12:42:39.087 回答
0

您可以简单地设置nodesnull

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 序列化程序是否可以为您执行此操作。

于 2017-02-09T09:06:56.817 回答
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; }
    }
}

输出

更新 如果您需要遍历所有列表,不仅第一项在主函数中使用 Do2(tree) 方法。

private static void Do2(List<Tree> t)
    {
        foreach (Tree tree in t)
        {
            if (tree.nodes.Count == 0)
                tree.nodes = null;
            else
                Do2(tree.nodes);
        }            
    }
于 2017-02-09T10:10:01.420 回答