一尘不染

如何通过LINQ展平树?

c#

所以我有简单的树:

class MyNode
{
 public MyNode Parent;
 public IEnumerable<MyNode> Elements;
 int group = 1;
}

我有一个IEnumerable<MyNode>。我想将所有列表MyNode(包括内部节点对象(Elements))作为一个平面列表Where
group == 1。如何通过LINQ做这样的事情?


阅读 273

收藏
2020-05-19

共1个答案

一尘不染

您可以像这样压扁一棵树:

IEnumerable<MyNode> Flatten(IEnumerable<MyNode> e) =>
    e.SelectMany(c => Flatten(c.Elements)).Concat(new[] { e });

然后,您可以group使用过滤Where(...)

要获得一些“风格要点”,请转换Flatten为静态类中的扩展功能。

public static IEnumerable<MyNode> Flatten(this IEnumerable<MyNode> e) =>
    e.SelectMany(c => c.Elements.Flatten()).Concat(e);

要获得“甚至更好的样式”的更多积分,请转换Flatten为采用一棵树和一个从节点生成后代的函数的通用扩展方法:

public static IEnumerable<T> Flatten<T>(
    this IEnumerable<T> e
,   Func<T,IEnumerable<T>> f
) => e.SelectMany(c => f(c).Flatten(f)).Concat(e);

像这样调用此函数:

IEnumerable<MyNode> tree = ....
var res = tree.Flatten(node => node.Elements);

如果您希望按顺序而不是按顺序展平,请在的两侧进行切换Concat(...)

2020-05-19