[英]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.