Reputation: 405
I have this model:
public class Node
{
public int Id { get; set; }
public string Name { get; set; }
public int? ParentId { get; set; }
}
I have The following data that comes from a database query:
nodes.Add(new Node { Id = 1, Name = "Node #1", ParentId = null });
nodes.Add(new Node { Id = 2, Name = "Node #2", ParentId = 1 });
nodes.Add(new Node { Id = 3, Name = "Node #3", ParentId = 2 });
nodes.Add(new Node { Id = 4, Name = "Node #4", ParentId = null });
nodes.Add(new Node { Id = 5, Name = "Node #5", ParentId = 2 });
nodes.Add(new Node { Id = 6, Name = "Node #6", ParentId = 2 });
nodes.Add(new Node { Id = 7, Name = "Node #7", ParentId = 1 });
nodes.Add(new Node { Id = 8, Name = "Node #8", ParentId = 5 });
nodes.Add(new Node { Id = 9, Name = "Node #9", ParentId = 4 });
nodes.Add(new Node { Id = 10, Name = "Node #10", ParentId = 4 });
I would like to sort the list and maintain the flat structure. The output I am expecting is this:
// 1 - Node #1 => NULL
// 2 - Node #2 => 1
// 3 - Node #3 => 2
// 5 - Node #5 => 2
// 8 - Node #8 => 5
// 6 - Node #6 => 2
// 7 - Node #7 => 1
// 4 - Node #4 => NULL
// 9 - Node #9 => 4
// 10 - Node #10 => 4
I was referring to this Stackoverflow answer but I didn't get the result I want.
Any help?
Upvotes: 2
Views: 598
Reputation: 20085
You can try creating recursive query in LINQ using SelectMany
as:
IEnumerable<Node> Recurcive(List<Node> nodeList, int? parentId)
{
return nodeList
.Where(x => x.ParentId == parentId)
.SelectMany(x =>
new[] { new Node
{ Id = x.Id, Name = x.Name, ParentId = x.ParentId } }
.Concat(Recurcive(nodeList, x.Id)));
}
foreach (var node in Recurcive(nodes, null))
Console
.WriteLine($"Id : {node.Id}\t, Name = {node.Name}\t, Parent = {node.ParentId}");
Output:
//Id: 1 , Name = Node #1 , Parent =
//Id: 2 , Name = Node #2 , Parent = 1
//Id: 3 , Name = Node #3 , Parent = 2
//Id: 5 , Name = Node #5 , Parent = 2
//Id: 8 , Name = Node #8 , Parent = 5
//Id: 6 , Name = Node #6 , Parent = 2
//Id: 7 , Name = Node #7 , Parent = 1
//Id: 4 , Name = Node #4 , Parent =
//Id: 9 , Name = Node #9 , Parent = 4
//Id: 10 , Name = Node #10 , Parent = 4
Upvotes: 0
Reputation: 117057
Here's how I would do it:
var nodes = new List<Node>()
{
new Node { Id = 1, Name = "Node #1", ParentId = null },
new Node { Id = 2, Name = "Node #2", ParentId = 1 },
new Node { Id = 3, Name = "Node #3", ParentId = 2 },
new Node { Id = 4, Name = "Node #4", ParentId = null },
new Node { Id = 5, Name = "Node #5", ParentId = 2 },
new Node { Id = 6, Name = "Node #6", ParentId = 2 },
new Node { Id = 7, Name = "Node #7", ParentId = 1 },
new Node { Id = 8, Name = "Node #8", ParentId = 5 },
new Node { Id = 9, Name = "Node #9", ParentId = 4 },
new Node { Id = 10, Name = "Node #10", ParentId = 4 },
};
var lookup = nodes.ToLookup(x => x.ParentId);
IEnumerable<Node> Flatten(int? parentId)
{
foreach (var node in lookup[parentId])
{
yield return node;
foreach (var child in Flatten(node.Id))
{
yield return child;
}
}
}
var output = Flatten(null).ToArray();
That little bit of recursion gives me:
Upvotes: 3
Reputation: 70523
I think you want this
nodes.OrderBy(n => n.ParentID ?? n.Id)
.ThenBy(n => n.Id);
Upvotes: 0