简体   繁体   English

通用树结构-如何填充组织结构图

[英]Generic Tree Structure - How to populate an org chart

I have what should be a fairly trivial problem but I want to make sure I'm doing this in the most "elegant" way possible in .Net 4.5 and I'd like some opinions from people smarter than me. 我有一个相当琐碎的问题,但我想确保在.Net 4.5中以最“优雅”的方式做到这一点,并且我希望有比我聪明的人提出一些意见。

I have a class that represents a generic tree structure as such: 我有一个代表这样的通用树结构的类:

   public class TreeNode<T>
    {
        List<TreeNode<T>> Children;

        T Item {get;set;}

        public TreeNode (T item)
        {
            Item = item;
        }

        public TreeNode<T> AddChild(T item)
        {
            TreeNode<T> nodeItem = new TreeNode<T>(item);
            Children.Add(nodeItem);
            return nodeItem;
        }
    }

Now, I have a Person class that represents an employee of the organization. 现在,我有一个Person类,代表该组织的一名员工。 Each Person object has an ID and a BossID that points to their superior. 每个Person对象都有一个ID和一个BossID指向其上级。

Multiple employees can have the same boss, hence why I am trying to create an organization chart with this tree structure. 多个员工可以拥有同一位老板,因此为什么我要尝试使用这种树形结构创建组织结构图。

The top node is going to be the Person object where BossID is null (it's an int? ). 顶部节点将是BossID为null的Person对象(这是一个int? )。 That I can quickly get with LINQ. 我可以很快使用LINQ。

It's the next step that is puzzling me a bit. 下一步让我有些困惑。 There are multiple approaches but they seem somewhat sloppy to me and I know there must be a much easier/elegant way to fill in the rest of the org chart. 有多种方法,但对我来说似乎有些草率,我知道必须有一种更轻松/优雅的方法来填写组织结构图的其余部分。

So right now I have a generic object of List<Person> holding all the employees, with their various BossID s and this generic tree structure that I can add child nodes to. 因此,现在我有了一个List<Person>的通用对象,该对象持有所有雇员,以及他们的各种BossID和可以添加子节点的这种通用树结构。

It's all very basic, but what is the proper sequence to fill the tree? 这都是非常基本的,但是填充树的正确顺序是什么? Am I recursively supposed to iterate down the line? 我是否应该递归迭代? I know there is backtracking involved here, which is where I'm getting stumped. 我知道这里涉及回溯,这就是我陷入困境的地方。

I apologize, my background is not in Computer Science, and if it was I realize that tree structures, linked lists, and everything else is trivial stuff. 我很抱歉,我的背景不是计算机科学专业,如果我意识到树结构,链表以及其他所有内容都是微不足道的。 But this is my first attempt and I want to see how it's done properly. 但这是我的第一次尝试,我想看看它是如何正确完成的。

I appreciate any guidance. 我感谢任何指导。

So, given you have a Person class defined as this: 因此,假设您定义了一个Person类:

public class Person
{
    public int ID;
    public int? BossID;
}

...and you have a List<Person> defined as people then this works: ...并且您将List<Person>定义为people则此方法有效:

var lookup = people.ToLookup(p => p.BossID);

Action<TreeNode<Person>> addChildren = null;
addChildren = p =>
{
    foreach (var child in lookup[p.Item.ID])
    {
        var childNode = p.AddChild(child);
        addChildren(childNode);
    }
};

var trees =
    from boss in lookup[null]
    select new TreeNode<Person>(boss);

foreach (var tree in trees)
{
    addChildren(tree);
}

This assumes that you may have more than one person with a null boss. 这是假设你可能有不止一个人用null的老板。 If you don't that's fine, just run this code and do trees.First() . 如果不行,请运行此代码并执行trees.First()

The definition of TreeNode<T> I used was this: 我使用的TreeNode<T>的定义是这样的:

public class TreeNode<T>
{
    private List<TreeNode<T>> Children;

    public T Item { get; set; }

    public TreeNode(T item)
    {
        this.Item = item;
        this.Children = new List<TreeNode<T>>();
    }

    public TreeNode<T> AddChild(T item)
    {
        var nodeItem = new TreeNode<T>(item);
        this.Children.Add(nodeItem);
        return nodeItem;
    }
}

You could shorten TreeNode<T> to this though: 您可以将TreeNode<T>缩短为:

public class TreeNode<T> : List<TreeNode<T>>
{
    public T Item { get; set; }

    public TreeNode(T item)
    {
        this.Item = item;
    }
}

...then your need to modify addChildren to this: ...然后您需要将addChildren修改为:

Action<TreeNode<Person>> addChildren = null;
addChildren = p =>
{
    foreach (var child in lookup[p.Item.ID])
    {
        var childNode = new TreeNode<Person>(child);
        p.Add(childNode);
        addChildren(childNode);
    }
};

...but then you'd have all of the standard List<> operators available for TreeNode<T> . ...但是您将拥有所有可用于TreeNode<T>的标准List<>运算符。

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

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