C# 在树结构中按ID属性定位实例
我有一个C类,它包含与其属性之一相同的类的列表:C# 在树结构中按ID属性定位实例,c#,.net,linq,tree,C#,.net,Linq,Tree,我有一个C类,它包含与其属性之一相同的类的列表: class MyClass { string id; List<MyClass> children; //other properties public MyClass(string Id, List<MyClass> Children) { id = Id; children = Children; } } 在我的程序中,这个类用于创建一
class MyClass
{
string id;
List<MyClass> children;
//other properties
public MyClass(string Id, List<MyClass> Children)
{
id = Id;
children = Children;
}
}
在我的程序中,这个类用于创建一个树结构,因此,某些项将没有子项。有没有一种方法可以在结构中定位一个ID,并从中递归返回树以获得父节点数组
我知道这类似于TreeView.FindNode,但如果可以,我希望避免使用派生类。我会使用递归:
List<MyClass> GetPathToId(string id2find)
{
if (Id == id2find) return new List<MyClass>(new[] { this });
if (Children == null) return null;
List<MyClass> result = Children.Select(e => e.GetPathToId(id2find)).FirstOrDefault(r => r != null);
if (result != null) result.Insert(0, this);
return result;
}
更新:正如医生正确指出的,由于我不知道你们的班级,孩子们可能是空的。我添加了一个空检查。这里有一个扩展方法,它使用递归进行检查
public static class Ex
{
public static List<MyClass> FindNode(this MyClass t, string id)
{
if (t.Id == id)
return new List<MyClass>() { t };
if (t.Children == null)
return null;
foreach (var child in t.Children)
{
var childResult = child.FindNode(id);
if (childResult != null)
return new List<MyClass>() { t }.Concat(childResult).ToList();
}
return null;
}
}
它将返回从根目录到包含特定id的实例的路径
var t1 = new MyClass("1", null);
var t2 = new MyClass("2", null);
var t3 = new MyClass("3", null);
var t4 = new MyClass("4", new List<MyClass>() { t1, t2, t3 });
var t5 = new MyClass("5", null);
var t6 = new MyClass("6", null);
var t7 = new MyClass("7", new List<MyClass>() { t5, t6 });
var t8 = new MyClass("8", new List<MyClass>() { t4, t7 });
var result = t8.FindNode("2");
if (result != null)
foreach (var myClass in result)
Console.WriteLine(myClass.Id);
结果是
八,
4.
二,
如果我对你的问题理解正确的话,我认为一个很好的方法就是使用两种方法。一个是按Id递归查找类,另一个是按需要返回数组中该类的父树
class MyClass
{
string id;
List<MyClass> children;
MyClass parent;
public MyClass(string id, List<MyClass> children)
{
this.id = id;
this.children = children;
foreach (var child in children)
{
child.parent = this;
}
}
public MyClass Parent { get { return this.parent; } }
public string Id { get { return this.id; } }
public List<MyClass> Children { get { return this.children; } }
}
static class Utility
{
public static MyClass FindMyClassById(IEnumerable<MyClass> myClasses, string id)
{
foreach (var myClass in myClasses)
{
if (myClass.Id == id)
{
return myClass;
}
if (myClass.Children != null && myClass.Children.Any())
{
return FindMyClassById(myClass.Children, id);
}
}
return null;
}
public static MyClass[] GetParentNodes(MyClass myClass)
{
var parents = new List<MyClass>();
while (myClass != null)
{
myClass = myClass.Parent;
parents.Add(myClass);
}
return parents.ToArray();
}
}
你有唯一的ID吗?是的,所有的ID都是唯一的。编辑:忘记e。在e.GetPathToId中创建StackOverflowException。如果没有id与search@doctor不,它返回null。我用上次编辑之前你读过的代码试过了。但为了更好的变化而进行了编辑。当Id用于没有任何子节点的节点时,它也会引发异常。@doctor为什么要这样做?好吧,如果Children为null,我想OP会在课堂的另一部分处理这个问题。对于not matchin Id,只有在层次结构中有大量级别时才会抛出。请证明你的意思。我在VisualStudio中尝试了它,它返回null而没有抛出!对于性能:好方法是使用async方法创建并取消令牌:-