我想就如何以有效的方式从项目列表中构建树来获得一些建议
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将是多余的
答案 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的新类,请创建它们而不是简单地将它们添加到父级。