2016-08-22 40 views
1

我有一个C#的对象列表,我需要进行透视和转换。但我不知道如何获得理想的结果。下面的代码讨论了结构,数据和期望的结果。我知道,我需要先对这些数据进行分组,然后进行转换。但我很困惑如何实现它。在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; } 
} 

回答

3

这里你可以采取一个办法:

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, 
    }; 
+0

谢谢你的快速帮助。这很棒。当排名或收入不适用于任何地区时,当前显示为0,我如何将其设置为空? – OpenStack

+0

@OpenStack删除'??新的Rev()'从所有'let'行开始,然后在'select'内使用'g?.Revenue','g?.Rank'等。 –

0

当你不使用C#6.0

var pivoted = 
    from x in revList.ToLookup(d => new { d.Id, d.Name }) 
    let g = x.SingleOrDefault(d => d.Region == "Global") ?? new Rev() 
    let u = x.SingleOrDefault(d => d.Region == "USA") ?? new Rev() 
    let e = x.SingleOrDefault(d => d.Region == "Euro") ?? new Rev() 
    let a = x.SingleOrDefault(d => d.Region == "APAC") ?? new Rev() 
    select new RevExtended 
    { 
     Id = x.Key.Id, 
     Name = x.Key.Name, 
     GlobalRevenue = g.Revenue == null ? null : g.Revenue, 
     GlobalRank = g.Rank == null ? null : g.Rank, 
     USARevenue = u.Revenue == null ? null : u.Revenue, 
     USARank = u.Rank == null ? null : u.Rank, 
     EuroRevenue = e.Revenue == null ? null: e.Revenue, 
     EuroRank = e.Rank == null ? null : e.Rank, 
     ApacRevenue = a.Revenue == null ? null : a.Revenue, 
     ApacRank = a.Rank == null ? null : a.Rank, 
    }; 
0

@OpenStack,你有一个基于最后一部分用于之前6.0的C#用户回答的接受答案。你的例子并不完全正确。有两个问题:

  • 您的示例将始终有一个Rev对象,因此对象引用 将永远不会为null。
  • 如果您确实允许空值(按照预期),则赋值逻辑不会保护您免于空值。

这里是公认的答案为C#版本比6.0更早的等价物:

var pivoted = 
    from x in revList.ToLookup(d => new { d.Id, d.Name }) 
    let g = x.SingleOrDefault(d => d.Region == "Global") 
    let u = x.SingleOrDefault(d => d.Region == "USA") 
    let e = x.SingleOrDefault(d => d.Region == "Euro") 
    let a = x.SingleOrDefault(d => d.Region == "APAC") 
    select new RevExtended 
    { 
     Id = x.Key.Id, 
     Name = x.Key.Name, 
     GlobalRevenue = g == null ? null : g.Revenue, 
     GlobalRank = g == null ? null : g.Rank, 
     USARevenue = u == null ? null : u.Revenue, 
     USARank = u == null ? null : u.Rank, 
     EuroRevenue = e == null ? null: e.Revenue, 
     EuroRank = e == null ? null : e.Rank, 
     ApacRevenue = a == null ? null : a.Revenue, 
     ApacRank = a == null ? null : a.Rank, 
    };  

如果你同意,你可以更新你的答案,以便它是正确的(复制和粘贴矿山如果你喜欢)我会删除这一个。