c# - 在 C# 中旋转多列

标签 c# .net linq c#-4.0 pivot

我有一个 C# 对象列表,我需要对其进行旋转和转换。但我不确定如何获得所需的结果。下面的代码讨论了结构、数据和期望的结果。我知道,我需要先对数据进行分组,然后再进行数据透视。但我很困惑如何实现它。

class Program
{
    static void Main(string[] args)
    {
        List<Rev> revList = new List<Rev>();
        Rev r = new Rev { Id = 1, Name = "One", Rank = 1, Region = "Global", Revenue = 600 }; revList.Add(r);
        r = new Rev { Id = 1, Name = "One", Rank = 1, Region = "USA", Revenue = 100 }; revList.Add(r);
        r = new Rev { Id = 1, Name = "One", Rank = 1, Region = "Euro", Revenue = 200 }; revList.Add(r);
        r = new Rev { Id = 1, Name = "One", Rank = 1, Region = "APAC", Revenue = 300 }; revList.Add(r);

        r = new Rev { Id = 2, Name = "Two", Rank = 2, Region = "Global", Revenue = 500 }; revList.Add(r);
        r = new Rev { Id = 2, Name = "Two", Rank = 2, Region = "USA", Revenue = 100 }; revList.Add(r);
        r = new Rev { Id = 2, Name = "Two", Rank = 3, Region = "APAC", Revenue = 400 }; revList.Add(r);

        r = new Rev { Id = 3, Name = "Three", Rank = 2, Region = "Global", Revenue = 300 }; revList.Add(r);
        r = new Rev { Id = 3, Name = "Three", Rank = 2, Region = "USA", Revenue = 100 }; revList.Add(r);
        r = new Rev { Id = 3, Name = "Three", Rank = 3, Region = "Euro", Revenue = 200 }; revList.Add(r);

        //Should result in THIS IS THE HARD CODED RESULT WHICH TRANFORM FUNCTION SHOULD GENERATE
        List<RevExtended> resultList = new List<RevExtended>();
        RevExtended res = new RevExtended{Name = "One", Id = 1, APACRevenue = 300, ApacRank = 1, EuroRank = 1, EurpRevenue = 200, GlobalRank = 1, GlobalRevenue = 600, USARank = 1, USARevenue = 100};
        res = new RevExtended { Name = "Two", Id = 2, APACRevenue = 400, ApacRank = 3, GlobalRank = 2, GlobalRevenue = 500, USARank = 2, USARevenue = 100 };
        res = new RevExtended { Name = "Three", Id = 3, EuroRank = 3, EurpRevenue = 200, GlobalRank = 2, GlobalRevenue = 300, USARank = 2, USARevenue = 100 };
    }

    public List<RevExtended> Transform(List<Rev> revList)
    {
        List<RevExtended> resultList = new List<RevExtended>();

        var query = from rev in revList
                    group rev by rev.Id into revGroup


        return resultList;
    }
}

public class Rev
{
    public string Name { get; set; }
    public int Id { get; set; }
    public int? Revenue { get; set; }
    public int? Rank { get; set; }
    public string Region { get; set; }
}

public class RevExtended
{
    public string Name { get; set; }
    public int Id { get; set; }

    public int? GlobalRevenue { get; set; }
    public int? GlobalRank { get; set; }

    public int? USARevenue { get; set; }
    public int? USARank { get; set; }

    public int? EurpRevenue { get; set; }
    public int? EuroRank { get; set; }

    public int? APACRevenue { get; set; }
    public int? ApacRank { get; set; }
}

最佳答案

这是您可以采用的一种方法:

var pivoted =
    from d in data
    group d by new { d.Id, d.Name } into region
    let g = region.SingleOrDefault(d => d.Region == "Global") ?? new Rev()
    let u = region.SingleOrDefault(d => d.Region == "USA") ?? new Rev()
    let e = region.SingleOrDefault(d => d.Region == "Euro") ?? new Rev()
    let a = region.SingleOrDefault(d => d.Region == "APAC") ?? new Rev()
    select new RevExtended
    {
        Id = region.Key.Id,
        Name = region.Key.Name,
        GlobalRevenue = g.Revenue,
        GlobalRank = g.Rank,
        UsaRevenue = u.Revenue,
        UsaRank = u.Rank,
        EuroRevenue = e.Revenue,
        EuroRank = e.Rank,
        ApacRevenue = a.Revenue,
        ApacRank = a.Rank,
    };

如果在没有区域的情况下需要 null 值,则需要更改模型以支持它们。

public class RevExtended
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int? GlobalRank { get; set; }
    public int? GlobalRevenue { get; set; }

    public int? UsaRank { get; set; }
    public int? UsaRevenue { get; set; }

    public int? EuroRank { get; set; }
    public int? EuroRevenue { get; set; }

    public int? ApacRank { get; set; }
    public int? ApacRevenue { get; set; }
}
var pivoted =
    from d in data
    group d by new { d.Id, d.Name } into region
    let g = region.SingleOrDefault(d => d.Region == "Global")
    let u = region.SingleOrDefault(d => d.Region == "USA")
    let e = region.SingleOrDefault(d => d.Region == "Euro")
    let a = region.SingleOrDefault(d => d.Region == "APAC")
    select new RevExtended
    {
        Id = region.Key.Id,
        Name = region.Key.Name,
        GlobalRevenue = g?.Revenue,
        GlobalRank = g?.Rank,
        UsaRevenue = u?.Revenue,
        UsaRank = u?.Rank,
        EuroRevenue = e?.Revenue,
        EuroRank = e?.Rank,
        ApacRevenue = a?.Revenue,
        ApacRank = a?.Rank,
    };

关于c# - 在 C# 中旋转多列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39085203/

相关文章:

c# - LINQ - .Select(n => n.Name) 和 .Select(n => new { n.Name } ) 之间的区别;

c# - 可以全屏打开程序的应用程序?

javascript - 如何使用 Ajax 将 WebSocket 数据从 View 发送到 Controller 以及将修改后的数据发送到 View

c# - 如何在不更改目标 .net 版本的情况下将 VS 2008 解决方案转换为 VS 2010?

c# - 如何获取屏幕上字符串的宽度和高度?

c# - 试图获得随机排序顺序

c# - 服务器控件事件未正确触发

c# - 如何在 Bot Framework 中禁用本地化程序

c# - C++/CLI 中是否存在 C# 的不安全等效项?

c# - 创建要应用于 IQueryable 的动态搜索的最简单方法