I am using C#
and I have a list of items that have a nullable parent ID property.
I need to convert this to a list of items that have a list of their children and keep going down generations until there are no items left.
My existing class
public class Item
{
public int Id { get; set; }
public int? ParentId { get; set; }
}
My first thoughts...
Create a class
public class ItemWithChildren
{
public Item Item { get; set; }
public List<ItemWithChildren> Children { get; set; }
}
Now I need some way to get a List<ItemWithChildren>
that has all the top level Item objects and their children into the Children
property.
Note that the nesting is not a set number of levels.
I was hoping there was an elegant LINQ query that would work. So far I just have this...
var itemsWithChildren = items.Select(a => new ItemWithChildren{ Item = a });
It is more readable to not use pure Linq for this task, but a mixture of Linq and looping.
Given the following container:
class Node
{
public int Id { get; set; }
public int? ParentId { get; set; }
public List<Node> Children { get; set; }
}
Then you can make the tree with the following code.
var nodes = new List<Node>
{
new Node{ Id = 1 },
new Node{ Id = 2 },
new Node{ Id = 3, ParentId = 1 },
new Node{ Id = 4, ParentId = 1 },
new Node{ Id = 5, ParentId = 3 }
};
foreach (var item in nodes)
{
item.Children = nodes.Where(x => x.ParentId.HasValue && x.ParentId == item.Id).ToList();
}
var tree = nodes.Where(x => !x.ParentId.HasValue).ToList();
This will handle any level of depth and return a proper tree.
Given the following method to print the tree:
private void PrintTree(IEnumerable<Node> nodes, int indent = 0)
{
foreach(var root in nodes)
{
Console.WriteLine(string.Format("{0}{1}", new String('-', indent), root.Id));
PrintTree(root.Children, indent + 1);
}
}
The output of this call is:
1
-3
--5
-4
2
If however you want to use pure Linq for this, you can do the following, however to me it is harder to read:
var tree = nodes.Select(item =>
{
item.Children = nodes.Where(child => child.ParentId.HasValue && child.ParentId == item.Id).ToList();
return item;
})
.Where(item => !item.ParentId.HasValue)
.ToList();
This might help ?
var itemsWithChildren = items.Select(a => new ItemWithChildren{
Item = a,
Children = items.Where(b => b.ParentId==a.Id)
.ToList()
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With