使用父引用从对象创建嵌套的项列表

Th4*_*Guy 5 c# linq

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

Cha*_*ham 5

对于此任务,不使用纯 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)


Sel*_*enç 2

这可能有帮助吗?

var itemsWithChildren = items.Select(a => new ItemWithChildren{ 
                                         Item = a,
                                         Children = items.Where(b => b.ParentId==a.Id)
                                                         .ToList()
                                    });
Run Code Online (Sandbox Code Playgroud)