从 C# 中的列表创建树,并进行分组

Create a tree from a list in C#, with grouping

我有这个class:

 class Foo 
 {
    Category1 Cat1;
    Category2 Cat2;
    Category3 Cat3;
    decimal Weight;
 }

每个Categoryi都有一个string Name属性

所以 Foos 的列表可能如下所示:

 Cat1  Cat2  Cat3  Weight
--------------------------------
 AP    SG     X     10
 AP    SG     S      5
 AP    J      X      5
 AP    AR     S     10
 NE    R      L      7
 ...

我想从列表中创建一棵树。即:
一个节点列表,作为一个节点:

 class Node
 {
    string Name;
    decimal Weight;
    List<Node> Children;
 }

使用此层次结构顺序:Category1、Category2、Category3,树将如下所示:

|--AP (Weight: 30)
|   |
|   |--SG (Weight: 15)
|   |   |-- X (Weight: 10)
|   |   |-- S (Weight: 5)
|   |
|   |--J (Weight: 5)
|   |   |-- X (Weight: 5)
|   |
|   |--AR (Weight: 10)
|       |-- S (Weight: 10)
|
|--NE (Weight: 7)
    |
    |-- R (Weight: 7)
        |-- L (Weight: 7)

问题:实现这个最优雅的方法是什么?我正在使用 LINQ 进行查询。

我知道我可以按 Cat1 分组,即:list.GroupBy(r => new { r.Cat1 }),然后在每个组中迭代,在每个组内我可以按 Cat2 等分组,等等。但是看起来不是很优雅而且还很依赖层级顺序...

你可以这样做:

var nodes = list
    .GroupBy(c1 => c1.Cat1.Name)
    .Select(c1 => new Node
    {
        Name = c1.Key,
        Weight = c1.Sum(x => x.Weight),
        Children = c1
            .GroupBy(c2 => c2.Cat2.Name)
            .Select(c2 => new Node
            {
                Name = c2.Key,
                Weight = c2.Sum(x => x.Weight),
                Children = c2.Select(c3 => new Node
                {
                    Name = c3.Cat3.Name,
                    Weight = c3.Weight,
                    Children = new List<Node>()
                }).ToList()
            }).ToList()

    }).ToList();