从项目列表中构建树

时间:2012-06-05 11:45:49

标签: c#

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

 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将是多余的

3 个答案:

答案 0 :(得分: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();
}

UPD:

为了简化将项目从一个父项移动到另一个父项,您需要在每个项目中存储对父项目的引用。类似的东西:

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

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

答案 1 :(得分: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));
}

答案 2 :(得分:1)

如果您不想/有链接:

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的新类,请创建它们而不是简单地将它们添加到父级。