2013-09-27 8 views
5

die folgende Klasse Gegeben:C# GroupBy - Erstellen mehrere Gruppierung Ebene

public class Transaction 
{ 
    public string Category { get; set; } 
    public string Form { get; set; } 
} 

Wie erhalte ich eine Gruppierung von Transaktionen, die sowohl von den Category und die Form gruppiert sind? Grundsätzlich

ich mag es Ausgabe wie folgt:

Category 1 
    Form 1 
     Transaction1 
     Transaction2 
     Transaction3 
     ... 
    Form 2 
     Transaction1 
     Transaction2 
     Transaction3 
     ... 
Category 2 
    Form 1 
     Transaction1 
     Transaction2 
     Transaction3 
     ... 
    Form 2 
     Transaction1 
     Transaction2 
     Transaction3 
     ... 

Antwort

6

endete ich mit dem folgenden, denn die Gruppierung vor der Iteration über die Sammlung vollständig sein muß.

Seed Einige Transaktionen

var cats = new[] { "Category 1", "Category 2", "Category 3" }; 
var frms = new[] { "Form 1", "Form 2", "Form 3" }; 
var transactions = new List<Transaction>(); 

for (var i = 0; i <= 150; i++) 
{ 
    transactions.Add(new Transaction 
    { 
     Category = i % 2 == 0 ? cats[0] : i % 3 == 0 ? cats[1] : cats[2], 
     Form = i % 5 == 0 ? frms[0] : i % 7 == 0 ? frms[1] : frms[2] 
    }); 
} 

Die Gruppierung

var groupedTransactions = transactions.GroupBy(x => x.Category) 
    .Select(x => new 
    { 
     Category = x.Key, 
     Forms = x.ToList() 
      .GroupBy(y => y.Form) 
    }); 

schreiben sie an die Konsole

foreach (var group in groupedTransactions.OrderBy(x => x.Category)) 
{ 
    Console.WriteLine(group.Category); 
    foreach (var form in group.Forms.OrderBy(x => x.Key)) 
    { 
     Console.WriteLine("\t" + form.Key); 
     foreach (var transaction in form) 
     { 
      Console.WriteLine("\t\t" + transaction.Id); 
     } 
    } 
} 
6

Hier ist ein Beispiel verschachtelte foreach-Schleifen verwenden, ich bin nicht sicher, wie Sie dies tun würden in einer einzigen Reihe von Linq Aussagen, vielleicht mit vielen von auswahlmanagern?

var transactions = new[]{ 
    new{Category = "1", Form = "1", Title = "Trans1" }, 
    new{Category = "1", Form = "1", Title = "Trans2" }, 
    new{Category = "1", Form = "1", Title = "Trans3" }, 
    new{Category = "1", Form = "2", Title = "Trans1" }, 
    new{Category = "1", Form = "2", Title = "Trans2" }, 
    new{Category = "1", Form = "2", Title = "Trans3" }, 
    new{Category = "2", Form = "1", Title = "Trans1" }, 
    new{Category = "2", Form = "1", Title = "Trans2" }, 
    new{Category = "2", Form = "1", Title = "Trans3" }, 
    new{Category = "1", Form = "3", Title = "Trans1" }, 
    new{Category = "1", Form = "3", Title = "Trans2" }, 
    new{Category = "1", Form = "3", Title = "Trans3" }, 
}; 

foreach(var byCategory in transactions.GroupBy(x => x.Category)) 
{ 
    Console.WriteLine(byCategory.Key); 
    foreach(var byForm in byCategory.GroupBy(x => x.Form)) 
    { 
     Console.WriteLine("\t" + byForm.Key); 
     foreach(var trans in byForm) 
     { 
      Console.WriteLine("\t\t" + trans.Title); 
     } 
    } 
} 

Nur weil ich neugierig war, was es aussehen würde, wie ich mit der folgenden aufkam, SOLLTEN SIE DAS NICHT IN DER PRODUKTION Code verwenden, wie es lächerlich ist (wenn Sie diese eine Datenstruktur zu tun haben, wie es gebrochen werden sollte up in so etwas wie Dictionary<CategoryName, FormGroup> oder etwas mit aussagekräftigen Typen)

Dictionary<string, Dictionary<string, List<string>>> tooManyDictionaries = transactions 
     .GroupBy(x => x.Category) 
     .ToDictionary(
      catGroup => catGroup.Key, 
      catGroup => catGroup 
       .GroupBy(x => x.Form) 
       .ToDictionary(
        formGroup => formGroup.Key, 
        formGroup => formGroup.Select(x => x.Title).ToList()));