首页 > 解决方案 > 使用 c# 将平面对象转换为层次结构

问题描述

我见过类似的问题,但没有回答我的情况。所以...

给定类型:

public class Flat
{
    public string Group1 { get; set; }
    public string Group2 { get; set; }  
    public int Value { get; set; }
}

public class Group1 
{
    public Name { get; set; }
    public Group2[] Group2 { get; set; }
}

public class Group2
{
    public Name { get; set; }
    public int[] Values;
}

我想将 Flat 数组转换为上面指定的Group1/Group2层次结构。数组如下:

var flats = new []
    {
        new Flat { Group1 = "G1", Group2 = "G1.1", Value = 12 },
        new Flat { Group1 = "G1", Group2 = "G1.1", Value = 22 },
        new Flat { Group1 = "G1", Group2 = "G1.2", Value = 13 },
        new Flat { Group1 = "G2", Group2 = "G1.1", Value = 14 },
        new Flat { Group1 = "G2", Group2 = "G2.2", Value = 15 },
    };

所以输出将等同于:

var result = new []
{
    new Group1 
    { 
        Name = "G1"
        Group2 = [] 
        {
            new Group2 
            { 
                Name = "G1.1" 
                Values = [] { 12, 22 }
            },
            new Group2 
            { 
                Name = "G1.2" 
                Values = [] { 13 }
            },
        }
    },
    new Group1 
    { 
        Name = "G2"
        Group2 = [] 
        {
            new Group2 
            { 
                Name = "G2.1" 
                Values = [] { 14 }
            },
            new Group2 
            { 
                Name = "G2.2" 
                Values = [] { 15 }
            },
        }
    }
}

我尝试过使用但失败了GroupBy

var result = flats
        .GroupBy(f => f.Group1)
        .Select(f => f.GroupBy(x => x.Group2).Select(y => y.Select(x => x.Value)));

我一直在摆弄这个,linqpad但没有找到解决方案。我最初一直在尝试匿名类型,但添加了组类型。

这可能linq吗?

标签: c#linqdata-structures

解决方案


您只需要使用 LINQ 在两个级别上构建分组:

var ans = flats.GroupBy(f => f.Group1)
               .Select(fg => new Group1 {
                                Name = fg.Key,
                                Group2 = fg.GroupBy(f => f.Group2).Select(fg2 => new Group2 {
                                                                            Name = fg2.Key,
                                                                            Values = fg2.Select(f => f.Value).ToArray()
                                                                          })
                                                                   .ToArray()
                       })
               .ToArray();

注意:通常,除非您对类型有特定需求(通常与其他代码的互操作性) ,否则最好选择ToList而不是。ToArrayArray


推荐阅读