2013-09-27 12 views
5

Biorąc pod uwagę następujące klasy:C# GroupBy - Tworzenie wielu poziomach grupowania

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

Jak mogę uzyskać grupowania operacji gospodarczych, które są zgrupowane zarówno przez Category i Form?

Zasadniczo chcę go do wyjścia tak:

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

Odpowiedz

6

skończyło się z następujących, ponieważ ugrupowanie muszą być kompletne przed iteracji nad kolekcji.

Seed niektórych transakcji

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] 
    }); 
} 

zgrupowania

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

zapisać go do konsoli

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

Oto przykład za pomocą zagnieżdżonych pętla foreach, nie jestem pewien, jak można to zrobić w jednym ciągiem wypowiedzi LINQ, może z dużą wybranych?

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); 
     } 
    } 
} 

Tylko dlatego, że byłem ciekawy co to będzie wyglądać wymyśliłem Poniżej, nie należy stosować to w kodzie produkcji, jak to jest śmieszne (jeśli masz strukturę danych jak to powinno być uszkodzony się w coś podobnego Dictionary<CategoryName, FormGroup> czy coś z sensownych typów)

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()));