Reputation: 213
Assume I have a Category which could have unlimited children and each child could also have unlimited children too.
Just curious, is there a way to retrieve all family of Root node using LINQ?
Upvotes: 1
Views: 900
Reputation: 726579
There are two common ways to process a recursive structure in C# - by using yield return
and by writing a recursive function. I prefer the second way, here is an example:
public static class TreeUtils {
public static IEnumerable<T> GetAllNodes<T>(
this T node
, Func<T,IEnumerable<T>> f)
{
return GetAllNodes(new[] {node}, f);
}
public static IEnumerable<T> GetAllNodes<T>(
this IEnumerable<T> e
, Func<T,IEnumerable<T>> f)
{
return e.SelectMany(c => f(c).GetAllNodes(f)).Concat(e);
}
}
You can use this utility class as follows:
class TreeNode<T> {
public T Content {get; set;}
public IEnumerable<TreeNode<T>> Dependents {get;set;}
}
foreach (TreeNode node in TreeUtils.GetAllNodes(root, n => n.Dependents)) {
Console.WriteLine(node.Content);
}
A somewhat cheating way would be to employ a "recursive" lambda:
using System;
using System.Collections.Generic;
public class Program {
class Node {
public int Data;
public IEnumerable<Node> Dependents { get; set; }
}
public static void Main() {
var root = Create(
10
, Create(5, Create(3), Create(7, Create(6), Create(8)))
, Create(20, Create(15), Create(30, Create(28), Create(40)))
);
// We cannot combine the declaration and definition here
Func<Node,IEnumerable<Node>> all = null;
// The recursive magic is in the following line
all = n => n.Dependents.SelectMany(d => all(d)).Concat(new[] {n});
// Here is how you can use it
foreach (var node in all(root)) {
Console.WriteLine(node.Data);
}
}
// Helper function for creating tree nodes
private static Node Create(int data, params Node[] nodes) {
return new Node { Data = data, Dependents = nodes };
}
}
Upvotes: 2
Reputation: 6280
Lambdas, upon which linq is very dependent, don't support the recursion needed to do such a thing in an intuitive manner; however, using let and the y-combinator you can so it in a non-intuitive manner. Here is a complicated example:
Hopefully somebody will come up with a more concise one. If so, pick them.
Upvotes: 1