2016-08-22 50 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, 
    };  

如果你同意,你可以更新你的答案,以便它是正確的(複製和粘貼礦山如果你喜歡)我會刪除這一個。