C# 从具有父引用的对象创建项目的嵌套列表
我正在使用C,并且我有一个具有可为空的父ID属性的项列表 我需要将其转换为一个项目列表,该列表包含其子项目的列表,并一直延续到没有项目剩下为止 我现有的班级C# 从具有父引用的对象创建项目的嵌套列表,c#,linq,C#,Linq,我正在使用C,并且我有一个具有可为空的父ID属性的项列表 我需要将其转换为一个项目列表,该列表包含其子项目的列表,并一直延续到没有项目剩下为止 我现有的班级 public class Item { public int Id { get; set; } public int? ParentId { get; set; } } 我的第一个想法 创建一个类 public class ItemWithChildren { public Item Item { get; set
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; }
}
这可能有用吗
var itemsWithChildren = items.Select(a => new ItemWithChildren{
Item = a,
Children = items.Where(b => b.ParentId==a.Id)
.ToList()
});
然后更新模型以实现它
public string Name { get; set; }
[DisplayName("Parent Category")]
public virtual Guid? CategoryUID { get; set; }
public virtual ICollection<Category> Categories { get; set; }
在这个任务中不使用纯Linq,而是混合使用Linq和循环,可读性更好 给定以下容器:
class Node
{
public int Id { get; set; }
public int? ParentId { get; set; }
public List<Node> Children { get; set; }
}
如果您想使用纯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();
我想你需要分两步来做。。。 我已经测试过了,它肯定有效
var items = new List<Item>();
items.Add(new Item { Id = 1, ParentId = null });
items.Add(new Item { Id = 2, ParentId = 1 });
items.Add(new Item { Id = 3, ParentId = 1 });
items.Add(new Item { Id = 4, ParentId = 3 });
items.Add(new Item { Id = 5, ParentId = 3 });
var itemsWithChildren = items.Select(a =>
new ItemWithChildren { Item = a }).ToList();
itemsWithChildren.ForEach(a =>
a.Children = itemsWithChildren.Where(b =>
b.Item.ParentId == a.Item.Id).ToList());
var root = itemsWithChildren.Single(a => !a.Item.ParentId.HasValue);
Console.WriteLine(root.Item.Id);
Console.WriteLine(root.Children.Count);
Console.WriteLine(root.Children[0].Children.Count);
Console.WriteLine(root.Children[1].Children.Count);
输出
一,
2.
0
2谢谢,但我认为这并不能解决可能存在深度的嵌套问题。@that--Guy_u我已经更新了我的答案,我认为您的ItemWithChildren类中的列表应该是List,否则它可能是无限循环。如果你想要这样,我不认为linq是最好的解决方案,尝试使用for循环或其他什么。Selectb=>b for?我认为你很接近,但它不会作为项工作。哪里将返回项集合而不是ItemWithChildren。我已在下面发布了我的答案。在相同entityx的列表或集合之前,虚拟关键字。ParentId.HasValue在where as x中不是必需的。ParentId为null时将永远不等于项。Id不是nullable@Mick很对,,这只是我身上过于保守的开发人员出现了。@foreach循环中的CharlesGraham正确地添加了子项,但退出循环后,所有子项再次为空。我不确定为什么在我的机器上运行这个精确的代码不会导致子项为空。我将添加一个输出示例。@That--Guy_uu已用输出更新。如果任何答案对您有效,请将其作为正确答案接受。谢谢@查莱斯格雷厄姆现在我回来工作了,我可以试试这些,一旦我开始工作,我会记下正确的答案。@CharlesGraham结论是什么?这看起来像是我想要的优雅的解决方案,但它会导致所有的孩子都是空的。我不明白为什么。与@CharlesGrahamI的答案相同,我编辑了答案。有几个错误,但在概念上基本相同。
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
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();
var items = new List<Item>();
items.Add(new Item { Id = 1, ParentId = null });
items.Add(new Item { Id = 2, ParentId = 1 });
items.Add(new Item { Id = 3, ParentId = 1 });
items.Add(new Item { Id = 4, ParentId = 3 });
items.Add(new Item { Id = 5, ParentId = 3 });
var itemsWithChildren = items.Select(a =>
new ItemWithChildren { Item = a }).ToList();
itemsWithChildren.ForEach(a =>
a.Children = itemsWithChildren.Where(b =>
b.Item.ParentId == a.Item.Id).ToList());
var root = itemsWithChildren.Single(a => !a.Item.ParentId.HasValue);
Console.WriteLine(root.Item.Id);
Console.WriteLine(root.Children.Count);
Console.WriteLine(root.Children[0].Children.Count);
Console.WriteLine(root.Children[1].Children.Count);