2

I have a C# object which after JSON Serialization becomes something like this:

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: []
}];

I want to remove all nodes that are empty i.e. [] from the object or just mark them as null , so my final object will look like

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
}];

The list is dynamic and can have many branches.Thanks. My C# class is this

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

For creating the tree List Object my function :

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());

Now I Get the Tree structure in

var tree = treeItems.First();

I need some logic so that it will put all nodes = null in all nested levels using linq preferably. So that I can use it bootstrap-treeview datasource.

Jyotirmaya Prusty
  • 278
  • 1
  • 8
  • 25
  • 1
    Just set those properties to null, perhaps? A [mcve] would really help here... (I don't see how Javascript or Bootstrap are really relevant here though - this is just C# producing JSON, right?) – Jon Skeet Feb 09 '17 at 08:36
  • 2
    Do you want to remove the empty items from the list before they are serialized? Really need to see the object 1st – Wheels73 Feb 09 '17 at 08:37
  • Please reduce to a minimum complete example (complete: all the bits necessary for someone to re-create). – Richard Feb 09 '17 at 08:38
  • Are you using JSON.NET for serialization? If so you can probably customize the serialization behavior to fit your needs... – Lucero Feb 09 '17 at 08:43

3 Answers3

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);
Engineer
  • 300
  • 1
  • 9
0

You can simply set nodes as null

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

Edit: For doing it recursively for sub levels:

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;
    }
}

Call it like below:

treeItems.RemoveEmptyNodes();

This might not be the best solution as recursion is not good for performance. You should check if your JSON serializer can do this for you by implementing custom code.

Nitish mittal
  • 31
  • 1
  • 5
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

UPDATE If you need to iterate through all list, not only first item use Do2(tree) method in main function.

private static void Do2(List<Tree> t)
    {
        foreach (Tree tree in t)
        {
            if (tree.nodes.Count == 0)
                tree.nodes = null;
            else
                Do2(tree.nodes);
        }            
    }
Klik Kliković
  • 364
  • 1
  • 5
  • 13