【问题标题】:Checking length of tree using linq使用 linq 检查树的长度
【发布时间】:2013-02-15 09:27:58
【问题描述】:

嗨,假设我有以下类型的树

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

假设树的根是

Element root = GetTree();

我知道可以使用递归检查这棵树的长度 但这可以使用 linq 检查这棵树的长度吗?

【问题讨论】:

  • 我会使用递归方法来计算树中元素的数量。但很高兴听到任何其他想法。好问题。
  • 树的长度是什么意思?最大深度?项目总数?

标签: c# linq tree


【解决方案1】:

您可以编写一个扩展方法来递归检索所有元素。

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

例如:

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;
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    添加新的扩展方法;

        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;
        }
    

    然后这样称呼它;

    int depthCount= a.CountX();
    

    【讨论】:

      【解决方案3】:

      据我所知,您不能使用递归 Linq,因为开箱即用的递归 lambdas 是不可能的。

      我能给出的最原始的答案是基于一个基于可重用 Fixpoint 运算符的递归 lambda 表达式。你会发现大部分的 Linq 机制。但恐怕fixpoint部分是没有纯Linq答案的原因。

      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());
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-06
        • 1970-01-01
        • 2016-07-23
        • 1970-01-01
        • 2015-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多