0

我想就如何以有效的方式从项目列表中构建树获得一些建议

 public class Item
    {
        public Item(int id, int? parentId)
        {
            Id = id;
            ParentId = parentId;
        }

        public int Id { get; private set; }
        public int? ParentId { get; private set; }
        public List<Item> SubItems  { get; set; }
    }

    private Item BuildATree()
    {
        var items = new List<Item>()
                        {
                            new Item(1, null),
                            new Item(2, 1),
                            new Item(3, 1),
                            new Item(4, 1),
                            new Item(5, 2),
                            new Item(6, 2),
                            new Item(7, 4),
                            new Item(8, 7),
                            new Item(9, 1),
                        };

        //Build a tree out of list items
    }

我期望的结果是每个项目都在其父项的 SubItems 列表中

不一定使用相同的 Item 类,因为 Ids 会是多余的

4

3 回答 3

2

我会使用 LINQ:

//Build a tree out of list items
foreach (Item item in items)
{
    item.SubItems = items.Where(i => i.ParentId.Value == item.Id).ToList();
}

升级版:

为了简化从一个父项到另一个父项的移动,您需要在每个项中存储对父项的引用。就像是:

public class Item
{
    public Item(int id, int? parentId)
    {
        Id = id;
        ParentId = parentId;
    }

    public int Id { get; private set; }
    public int? ParentId { get; private set; }
    public List<Item> SubItems  { get; set; }

    private Item _parent;
    public Item Parent 
    {
        get { return _parent; }
        set
        {
            if (_parent != null)
                _parent.SubItems.Remove(this);
            _parent = value;
            if (_parent != null)
                _parent.SubItems.Add(this);
        }
    }
}

如果您以这种方式实现,那么只需通过此属性设置新的父项就足以修改新旧父项的子项集合 - 但请注意,您还需要更复杂的列表初始化机制。

于 2012-06-05T11:49:50.927 回答
2

足够有效的解决方案

private void RecursiveBuilder(ref Item i, IEnumerable<Item> li)
{
    var item = i;
    i.SubItems = (from n in li where n.ParentId == item.Id select n).ToList();
    i.SubItems.ForEach(f => RecursiveBuilder(ref f, li));
}
于 2012-06-11T11:46:37.097 回答
1

如果您不想要/拥有 Link :

Dictionary<int,Item> dic = new Dictionary<int,Item>();
foreach(Item item in items)
{
    Item parent;
    if(item.ParentId!=null && dic.TryGetValue(item.ParentId, out parent))
        parent.SubItems.Add(item);
    else
        dic.Add(item.Id, item);
}
Item root = dic[1];

我认为总会有一个 id = 1 的 Item ,这就是树的根。

如果您想使用没有 id 的新类,请创建它们而不是简单地将它们添加到它们的父级。

于 2012-06-05T11:58:33.520 回答