用LINQ表达式创建树

InT*_*ons 5 c# linq multidimensional-array

我有以下由存储过程返回的字段的C#列表:

CarrierId   ParentCarrierId Name Descrition
1            NULL            A         AA
2              1             B         BB
3              1             C         CC
4              3             D         DD
5            NULL            E         EE
Run Code Online (Sandbox Code Playgroud)

我需要从此输出构造一个嵌套的对象列表

因此,运营商的每个对象都应具有其所有子代的列表。谁能帮助我构建LINQ代码来完成此任务?

所需结果:

 CarrierId = 1
      |__________________ CarrierId = 2
      |__________________ CarrierId = 3
                              |___________________ CarrierId = 4

 CarrierId = 5
Run Code Online (Sandbox Code Playgroud)

所需结果应如上所述

Tim*_*ter 1

你原来的问题有点不同。我认为每个运营商都应该保存其所有后代的列表。现在看来你只想持有所有直系孩子。这很简单:

c.Children = carrierList.Where(child => child.ParentCarrierId == c.CarrierId).ToList();
Run Code Online (Sandbox Code Playgroud)

如果您希望将其作为 LINQ 查询,那么您必须创建以下新实例Carrier

List<Carrier> rootCarriers = carrierList
    .Select(c => new Carrier { 
        CarrierId = c.CarrierId,
        Name = c.Name,
        Descrition = c.Descrition,
        ParentCarrierId = c.ParentCarrierId,
        Children = carrierList
            .Where(child => child.ParentCarrierId == c.CarrierId)
            .ToList()
    })
    .Where(c => !c.ParentCarrierId.HasValue)
    .ToList(); 
Run Code Online (Sandbox Code Playgroud)

该查询还根据需要删除所有不是根载体(有父母)的内容。

下面显示了两个不同属性Children和的两种方法Descendants,后者甚至返回孙子,依此类推。

public class Carrier
{
    public List<Carrier> Descendants { get; set; }
    public List<Carrier> Children { get; set; }

    public static IEnumerable<Carrier> TraverseDescendants(IEnumerable<Carrier> allCarriers, Carrier rootCarrier)
    {
        Queue<Carrier> queue = new Queue<Carrier>();
        var children = allCarriers.Where(c => c.ParentCarrierId == rootCarrier.CarrierId);
        foreach (Carrier c in children)
            queue.Enqueue(c);
        while (queue.Count > 0)
        {
            Carrier child = queue.Dequeue();
            yield return child;
            var grandchildren = allCarriers.Where(c => c.ParentCarrierId == child.CarrierId);
            foreach (Carrier c in grandchildren)
                queue.Enqueue(c);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用 ,您可以在类中TraverseDescendents初始化。List<Carrier> Descendents-listChildren是一个简单的 LINQ 查询:

foreach (Carrier c in carrierList)
{
    c.Descendants = Carrier.TraverseDescendants(carrierList, c).ToList();
    c.Children = carrierList.Where(child => child.ParentCarrierId == c.CarrierId).ToList();
}
Run Code Online (Sandbox Code Playgroud)