Let say we have a class
Category
{
ID,
Name,
ParentID
}
and a List
1, \'Item 1\', 0
2, \'Item 2\', 0
3, \'Item 3\'
Here's the "LINQ-only" version:
Func build = null;
build = (p, n) =>
{
return (from x in categories
where x.ParentID == p
from y in new[]
{
"".PadLeft(n)+ x.Name
}.Union(build(x.ID, n + 1))
select y).ToArray();
};
var lines = build(0, 0);
Yes, it's recursive LINQ.
Per NVA's request, here's the way to make all "orphan" records become root records:
Func, int, string[]> build = null;
build = (ps, n) =>
{
return (from x in categories
where ps.Contains(x.ParentID)
from y in new[]
{
"".PadLeft(n)+ x.Name
}.Union(build(new [] { x.ID }, n + 1))
select y).ToArray();
};
var roots = (from c in categories
join p in categories on c.ParentID equals p.ID into gps
where !gps.Any()
orderby c.ParentID
select c.ParentID).Distinct();
var lines = build(roots, 0);