简体   繁体   English

使用 Linq 搜索分层数据

[英]Search Hierarchical Data Using Linq

I am trying to search hierarchical data based on the advice provided in this question How to search Hierarchical Data with Linq .我正在尝试根据这个问题How to search Hierarchical Data with Linq中提供的建议来搜索分层数据。 However, I am stuck.但是,我被困住了。

在此处输入图像描述

I have placed the sample code here.我已将示例代码放在这里。

I don't think this is right我不认为这是正确的

var result = NodeTypes[0].Flatten(x => x.Node).Where(y => ((ModelType)(y.Item)).ModelId == 2345);

as I want to search all nodes and the target node could be at any depth,因为我想搜索所有节点并且目标节点可以在任何深度,

I prefer to use a extension method to iterate the tree, something like:我更喜欢使用扩展方法来迭代树,例如:

        public static IEnumerable<T> DepthFirst<T>(IEnumerable<T> roots, Func<T, IEnumerable<T>> selector)
        {
            var stack = new Stack<T>();
            foreach (var r in roots)
            {
                stack.Push(r);
            }
            while (stack.Count > 0)
            {
                var current = stack.Pop();
                yield return current;
                foreach (var child in selector(current))
                {
                    stack.Push(child);
                }
            }
        }

Called like DepthFirst(nodeTypes, n => n.Node) , and produces a iterator of all nodes in the tree, regardless of depth.DepthFirst(nodeTypes, n => n.Node)一样调用,并生成树中所有节点的迭代器,无论深度如何。 The Flatten method from the linked answer should probably also work, since it is recursive, but it will likely create a tree of linq iterators, so I would expect it to have substantial overhead when doing the iteration.链接答案中的Flatten方法可能也可以工作,因为它是递归的,但它可能会创建一个 linq 迭代器树,所以我希望它在进行迭代时会有很大的开销。

Then it should simply be an issue if filtering out the nodes you are searching for:如果过滤掉您正在搜索的节点,那么它应该只是一个问题:

DepthFirst(nodeTypes, n => n.Node).Where(n => n.Item.ModelId == 2345);

If you want to do a BreadthFirst search instead you simply replace the stack with a queue.如果您想进行广度优先搜索,只需将堆栈替换为队列即可。 If you can have cycles in your graph you need to add a hashSet of visited nodes, and check this before traversing each node.如果您的图中可以有循环,则需要添加已访问节点的 hashSet,并在遍历每个节点之前进行检查。

You have to write your own flatten method like this你必须像这样编写自己的 flatten 方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication35
{
    class Program
    {
        static void Main(string[] args)
        {
            NodeType root = new NodeType()
                {
                    NodeTypeDescription = "abc",
                    Item = new ModelType() { ModelId = 123, ModelTitle = "123" },
                    Node = new NodeType[] {
                        new NodeType() { Item = "456", Node = null, NodeTypeDescription = "empty"},
                        new NodeType() { Item = "789", Node = null, NodeTypeDescription = "empty"},
                        new NodeType() { Item = "abc", Node = null, NodeTypeDescription = "empty"},
                    }
                };
            Dictionary<long, ModelType> nodes = root.Flaten(root);
           
        }
    }
    public class ModelType
    {
        public string ModelTitle;
        public long ModelId;
    }

    public class NodeType
    {
        public string NodeTypeDescription { get; set; }
        public object Item { get; set; }
        public NodeType[] Node { get; set; }

        public Dictionary<long, ModelType> Flaten(NodeType node)
        {
            Dictionary<long, ModelType> models = null;
            List<KeyValuePair<long, ModelType>> children = node.FlatenRecursive(node);

            if (node.GetType() == typeof(ModelType))
            {
                models = new Dictionary<long, ModelType>(); 

                models.Add(((ModelType)node.Item).ModelId, (ModelType)node.Item);
            }
            if (children != null)
            {
                foreach (KeyValuePair<long, ModelType> child in children)
                {
                    if (models == null) models = new Dictionary<long, ModelType>();
                    models.Add(child.Key, child.Value);
                }
            }
            return models;
        }
        public List<KeyValuePair<long,ModelType>> FlatenRecursive(NodeType node)
        {
            List<KeyValuePair<long, ModelType>> models = null;
            if(node.Item.GetType() == typeof(ModelType))
            {
                models = new List<KeyValuePair<long, ModelType>>();
                models.Add(new KeyValuePair<long,ModelType>(((ModelType)node.Item).ModelId, (ModelType)node.Item));
            }
            if (node.Node != null)
            {
                foreach (NodeType child in node.Node)
                {
                    List<KeyValuePair<long, ModelType>> children = child.FlatenRecursive(child);
                    if (children != null)
                    {
                        if (models == null) models = new List<KeyValuePair<long, ModelType>>();
                        models.AddRange(children);
                    }
                   
                }
            }
            return models;
        }
    }
    
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM