[英]Checking length of tree using linq
嗨,我說我有以下類型的樹
public class Element
{
public List<Element> element;
}
讓我們說樹的根是
Element root = GetTree();
我知道可以使用遞歸來檢查這棵樹的長度,但是這可以使用linq來檢查這棵樹的長度嗎?
您可以編寫一個擴展方法來遞歸檢索所有元素。
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;
}
}
}
}
添加新的擴展方法;
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();
據我所知,你不能反復使用Linq,因為沒有開箱即用的遞歸lambda。
我能給出的最原始的答案是基於一個基於可重用的Fixpoint運算符的遞歸lambda表達式。 你會發現大多數Linq機制。 但我擔心固定點部分是沒有沒有純粹的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());
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.