我正在尝试根据How to search Hierarchical Data with Linq问题中提供的建议搜索分层数据,但是,我卡住了。
var NodeTypes = new NodeType[] {
new NodeType{
NodeTypeDescription = "First Level",
Item = new CodeType(){ CodeValue = "01" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "First Child Level 0101",
Item = new CodeType(){ CodeValue = "0101" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Target Level Description",
Item = new ModelType(){ ModelId = 1234, ModelTitle = "Target-1234" },
Node = null
}
}
},
new NodeType{
NodeTypeDescription = "First Child Level 0102",
Item = new CodeType(){ CodeValue = "0102" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Target Level Description",
Item = new ModelType(){ ModelId = 2345, ModelTitle = "Target-2345" },
Node = null
}
}
}
}
},
new NodeType{
NodeTypeDescription = "Second Level",
Item = new CodeType(){ CodeValue = "02" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Second Child Level 0201",
Item = new CodeType(){ CodeValue = "0201" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Second Child Level 020101",
Item = new CodeType(){ CodeValue = "020101" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Target Level Description",
Item = new ModelType(){ ModelId = 2345, ModelTitle = "Target-2345" },
Node = null
}
}
}
}
},
new NodeType{
NodeTypeDescription = "Second Child Level 0202",
Item = new CodeType(){ CodeValue = "0202" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Target Level Description",
Item = new ModelType(){ ModelId = 3456, ModelTitle = "Target-3456" },
Node = null
}
}
}
}
}
};
我已经把sample code放在这里了。
public static class Extensions
{
public static IEnumerable<T> Flatten<T>(this T source, Func<T, IEnumerable<T>> selector)
{
return selector(source).SelectMany(c => Flatten(c, selector))
.Concat(new[] { source });
}
}
public class ModelType
{
public string ModelTitle;
public long ModelId;
}
public class CodeType
{
public string CodeValue;
}
public class NodeType
{
public string NodeTypeDescription { get; set; }
public object Item { get; set; }
public NodeType[] Node { get; set; }
}
public class Program
{
public static void Main()
{
var NodeTypes = new NodeType[] {
new NodeType{
NodeTypeDescription = "First Level",
Item = new CodeType(){ CodeValue = "01" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "First Child Level 0101",
Item = new CodeType(){ CodeValue = "0101" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Target Level Description",
Item = new ModelType(){ ModelId = 1234, ModelTitle = "Target-1234" },
Node = null
}
}
},
new NodeType{
NodeTypeDescription = "First Child Level 0102",
Item = new CodeType(){ CodeValue = "0102" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Target Level Description",
Item = new ModelType(){ ModelId = 2345, ModelTitle = "Target-2345" },
Node = null
}
}
}
}
},
new NodeType{
NodeTypeDescription = "Second Level",
Item = new CodeType(){ CodeValue = "02" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Second Child Level 0201",
Item = new CodeType(){ CodeValue = "0201" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Second Child Level 020101",
Item = new CodeType(){ CodeValue = "020101" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Target Level Description",
Item = new ModelType(){ ModelId = 2345, ModelTitle = "Target-2345" },
Node = null
}
}
}
}
},
new NodeType{
NodeTypeDescription = "Second Child Level 0202",
Item = new CodeType(){ CodeValue = "0202" },
Node = new NodeType[]{
new NodeType{
NodeTypeDescription = "Target Level Description",
Item = new ModelType(){ ModelId = 3456, ModelTitle = "Target-3456" },
Node = null
}
}
}
}
}
};
var result = NodeTypes[0].Flatten(x => x.Node).Where(y => ((ModelType)(y.Item)).ModelId == 2345);
}
}
我觉得这样不对
var result = NodeTypes[0].Flatten(x => x.Node).Where(y => ((ModelType)(y.Item)).ModelId == 2345);
因为我想搜索所有节点并且目标节点可以在任何深度,
另一个问题...
在扁平化层次结构之后,我们如何从父节点或兄弟节点中获取细节呢?比如,我想从其父节点的兄弟节点Item中提取codeValue。
var result2 = DepthFirst<NodeType>(NodeTypes, n => n.Node).ToList();
var result1 = result2.Where(n => n.Item.GetType() == typeof(ModelType) && ((ModelType)n.Item).ModelId == 2345).ToList();
2条答案
按热度按时间cbjzeqam1#
我更喜欢使用扩展方法来迭代树,类似于:
像
DepthFirst(nodeTypes, n => n.Node)
一样调用,并生成树中所有节点的迭代器,而不管深度如何。来自链接答案的Flatten
方法可能也会工作,因为它是递归的,但它可能会创建一个linq迭代器树,所以我认为它在进行迭代时会有大量的开销。那么如果过滤掉您正在搜索的节点,这应该只是一个问题:
如果你想使用广度优先搜索,你只需用队列替换堆栈;如果你的图中可以有循环,你需要添加一个已访问节点的哈希集,并在遍历每个节点之前检查它。
bvjveswy2#
您必须编写自己的flatten方法,如下所示