嗨,可以说我有以下类型的树
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 机制。但是恐怕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());
}
}