c# - 从具有父引用的对象创建嵌套的项目列表

标签 c# linq

我正在使用 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/

相关文章:

c# - 如何删除 C# Visual Studio if 语句中的换行符

c# - 为什么调用这个方法?

c# - WCF 数据服务 : add two new objects to the database with links between them

c# - 为什么循环中的任务工厂打印超出循环索引?

c# - Linq 表达式 : Left Join Duplicating Rows

c# - 如何传递要使用 LINQ 调用的函数委托(delegate)?

c# - 在 linq 查询中切换大小写

c# - 在给定属性的列表中获取项目的索引

c# - 带有方括号格式的 XML/Json

c# - ASP.net MVC3如何编辑sql数据库