简体   繁体   中英

Checking length of tree using linq

Hi lets say i have tree of following type

public class Element
{
    public List<Element> element;
}

lets say root of the tree is

Element root = GetTree();

I know it is possible to check length of this tree using recursion but is this possible to check length of this tree using linq?

You could write an extension method to retrieve all elements recursively.

var allElements = root.element.Traverse(el => el.element);

For example:

public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse)
{
    foreach (T item in source)
    {
        yield return item;

        IEnumerable<T> seqRecurse = fnRecurse(item);
        if (seqRecurse != null)
        {
            foreach (T itemRecurse in Traverse(seqRecurse, fnRecurse))
            {
                yield return itemRecurse;
            }
        }
    }
}

Add a new extension method;

    public static int CountX(this Element e)
    {
        int temp = 0;
        if (e.element != null)
        {
            temp = e.element.Count;
            e.element.ForEach(q => temp += q.CountX());
        }
        return temp;
    }

and call it like;

int depthCount= a.CountX();

As far as I know, you can not have recusive Linq, because having recursive lambdas is not possible out of the box.

Most original answer I can give is based on a recursive lambda expression based on a reusable Fixpoint operator. You will find most of Linq mechanisms. But I am afraid the fixpoint part is the reason why there is no no pure Linq answer.

public static class FixPoint
{
    // Reusable fixpoint operator
    public static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f)
    {
        return t => f(Fix<T, TResult>(f))(t);
    }
}

public class Element
{
    public List<Element> element;


    public int CalculateMaxDepth()
    {
        return FixPoint.Fix<List<Element>, int>(
            // recursive lambda
            f =>
            listElement => listElement == null || listElement.Count == 0 
                ? 0 
                : 1 + listElement.Select(e => f(e.element)).Max())
            (this.element);
    }

    [Test]
    public  void myTest()
    {
        var elt = new Element() { element = new List<Element> { new Element() { element = new List<Element> { new Element() { element = new List<Element> { new Element() } } } } } };
        Assert.AreEqual(3, elt.CalculateMaxDepth());
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM