SelectMany to flatten a nested structure

亡梦爱人 提交于 2019-12-06 07:31:46
Yves M.

This is a naturally recursive problem. Using a recursive lambda, try something like:

Func<Node, IEnumerable<Node>> flattener = null;
flattener = n => new[] { n }
    .Concat(n.Nodes == null 
        ? Enumerable.Empty<Node>()
        : n.Nodes.SelectMany(flattener));

Note that when you make a recursive Func like this, you must declare the Func separately first, and set it to null.

You could also flatten the list using an iterator-block method:

public static IEnumerable<Node> Flatten(Node node)
{
    yield return node;
    if (node.Nodes != null)
    {
        foreach(var child in node.Nodes)
            foreach(var descendant in Flatten(child))
                yield return descendant;
    }
}

Either way, once the tree is flattened you can do simple Linq queries over the flattened list to find nodes:

flattener(node).Where(n => n.Type == myType);

Response adapted from: https://stackoverflow.com/a/17086572/1480391

You should implement a method Node.GetFlattened, which returns the node itself and then calls itself on all subnodes:

public IEnumerable<Node> GetFlattened()
{
    yield return this;
    foreach (var node in this.Nodes.SelectMany(n => n.GetFlattened()))
        yield return node;
}

You would then be able to call this method and it recursively returns all nodes regardless of their depth. This is a depth-first search, if you want a breadth-first search, you will have to try another approach.

class MyXml
{
    public List<Node> AllNodes()
    {
        List<Node> allNodes = new List<Node>();
        foreach (var node in Content)
            AddNode(node, nodes);
    }

    public void AddNode(Node node, List<Node> nodes)
    {
        nodes.Add(node);
        foreach (var childNode in node.Nodes)
            AddNode(childNode, nodes);
    }

    public List<Node> AllNodesOfType(NodeType nodeType)
    {
       return AllNodes().Where(n => n.NodeType == nodeType);
    }
}

First flatten the list with a function and query on that.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!