我正在使用 C#
我有一个项目列表,这些项目具有可为空的父 ID 属性。
我需要将其转换为包含其子项列表的项列表,并继续向下传递直到没有项为止。
我现有的类(class)
public class Item
{
public int Id { get; set; }
public int? ParentId { get; set; }
}
我的第一个想法...
创建一个类
public class ItemWithChildren
{
public Item Item { get; set; }
public List<ItemWithChildren> Children { get; set; }
}
现在我需要一些方法来获得 List<ItemWithChildren>
将所有顶级 Item 对象及其子对象放入 Children
属性(property)。
请注意,嵌套不是固定的层数。
我希望有一个优雅的 LINQ 查询可以工作。到目前为止,我只有这个……
var itemsWithChildren = items.Select(a => new ItemWithChildren{ Item = a });
最佳答案
对于这个任务,不使用纯 Linq 而是混合使用 Linq 和循环会更具可读性。
给定以下容器:
class Node
{
public int Id { get; set; }
public int? ParentId { get; set; }
public List<Node> Children { get; set; }
}
然后你可以用下面的代码来制作树。
var nodes = new List<Node>
{
new Node{ Id = 1 },
new Node{ Id = 2 },
new Node{ Id = 3, ParentId = 1 },
new Node{ Id = 4, ParentId = 1 },
new Node{ Id = 5, ParentId = 3 }
};
foreach (var item in nodes)
{
item.Children = nodes.Where(x => x.ParentId.HasValue && x.ParentId == item.Id).ToList();
}
var tree = nodes.Where(x => !x.ParentId.HasValue).ToList();
这将处理任何级别的深度并返回适当的树。
给定以下打印树的方法:
private void PrintTree(IEnumerable<Node> nodes, int indent = 0)
{
foreach(var root in nodes)
{
Console.WriteLine(string.Format("{0}{1}", new String('-', indent), root.Id));
PrintTree(root.Children, indent + 1);
}
}
这个调用的输出是:
1
-3
--5
-4
2
如果你想为此使用纯 Linq,你可以执行以下操作,但对我来说它更难阅读:
var tree = nodes.Select(item =>
{
item.Children = nodes.Where(child => child.ParentId.HasValue && child.ParentId == item.Id).ToList();
return item;
})
.Where(item => !item.ParentId.HasValue)
.ToList();
关于c# - 从具有父引用的对象创建嵌套的项目列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21472941/