在树结构中通过 ID 属性 定位实例

Locating instance by ID property in tree structure

我有一个 C# class,其中包含一个 class 与其属性之一相同的列表:

class MyClass
{
    string id;
    List<MyClass> children;
    //other properties

    public MyClass(string Id, List<MyClass> Children)
    {
        id = Id;
        children = Children;
    }
}

在我的程序中,此 class 用于创建树结构(因此,某些项目不会有子项目)。有没有办法在结构中找到一个 ID,然后从那里向下递归树以获得父节点数组?

我知道这类似于 TreeView.FindNode() 但我想尽可能避免派生 class。

我会用递归来做:

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;
}

更新:正如医生正确指出的那样,因为我不知道您的 class,Children 可能为空。我添加了空检查。

这是一个使用递归实现的扩展方法

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;
    }
}

它将return从根目录到包含特定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);

结果是

8
4
2

如果我对您的问题的理解正确,我认为一种好的方法是使用两种方法。一个通过 Id 递归地找到你的 class,另一个到数组中那个 class 的 return 父树,就像你想要的那样。

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();
    }
}