我正在使用C#,我有一个具有可空父ID属性的项目列表.
我需要将其转换为具有子女列表的项目列表,并继续下去,直到没有项目为止.
我现有的课
public class Item
{
public int Id { get; set; }
public int? ParentId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我的第一个想法......
创建一个类
public class ItemWithChildren
{
public Item Item { get; set; }
public List<ItemWithChildren> Children { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在我需要一些方法来获得List<ItemWithChildren>具有所有顶级Item对象及其子项的Children属性.
请注意,嵌套不是一组设定的级别.
我希望有一个优雅的LINQ查询可以工作.到目前为止我只有这个......
var itemsWithChildren = items.Select(a => new ItemWithChildren{ Item = a });
Run Code Online (Sandbox Code Playgroud)
对于此任务,不使用纯 Linq,而是使用 Linq 和循环的混合,可读性更高。
给定以下容器:
class Node
{
public int Id { get; set; }
public int? ParentId { get; set; }
public List<Node> Children { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后您可以使用以下代码制作树。
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();
Run Code Online (Sandbox Code Playgroud)
这将处理任何深度级别并返回适当的树。
给出以下打印树的方法:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
此调用的输出是:
1
-3
--5
-4
2
Run Code Online (Sandbox Code Playgroud)
但是,如果您想为此使用纯 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();
Run Code Online (Sandbox Code Playgroud)
这可能有帮助吗?
var itemsWithChildren = items.Select(a => new ItemWithChildren{
Item = a,
Children = items.Where(b => b.ParentId==a.Id)
.ToList()
});
Run Code Online (Sandbox Code Playgroud)