2009-10-02 9 views
23

Widziałem prosty przykład .NET funkcji Łącznej działa tak:LINQ kruszywa typy złożone w ciąg

string[] words = { "one", "two", "three" }; 
var res = words.Aggregate((current, next) => current + ", " + next); 
Console.WriteLine(res); 

Jak mógłby funkcja „agregat” być stosowane, jeżeli chcesz agregować bardziej złożone typy? Na przykład: klasa 2 własności, takich jak „klucz” i „wartości” i chcesz wyjście tak:

"MyAge: 33, MyHeight: 1.75, MyWeight:90" 

Odpowiedz

40

Masz dwie opcje:

  1. projekt na string a następnie zagregowane:

    var values = new[] { 
        new { Key = "MyAge", Value = 33.0 }, 
        new { Key = "MyHeight", Value = 1.75 }, 
        new { Key = "MyWeight", Value = 90.0 } 
    }; 
    var res1 = values.Select(x => string.Format("{0}:{1}", x.Key, x.Value)) 
           .Aggregate((current, next) => current + ", " + next); 
    Console.WriteLine(res1); 
    

    Ma to tę zaletę, używając pierwszej string elementu jako nasion (no prepended ","), ale zużyje więcej pamięci na ciągi utworzone w procesie.

  2. pomocą łączną przeciążenia, który przyjmuje nasion, może StringBuilder:

    var res2 = values.Aggregate(new StringBuilder(), 
        (current, next) => current.AppendFormat(", {0}:{1}", next.Key, next.Value), 
        sb => sb.Length > 2 ? sb.Remove(0, 2).ToString() : ""); 
    Console.WriteLine(res2); 
    

    Drugi pełnomocnik przekształca naszych StringBuilder w string, stosując warunkowy do przycinania początkowy „”.

+0

Idealne, właśnie to, czego szukałem, więc mogłem je wszystkie odmierzać, od czasu, toczenie własnych pętli było szybsze (w teście mam tylko 1 lub 2 przedmioty) – Myster

+0

Z tak małą liczbą pozycji na liście , wydajność wykonania konfiguracji "dodatkowych" modułów wyliczających dla Select/Aggregate wydaje się dość surowa w porównaniu z bardziej imperatywnym rozwiązaniem. Podobnie jak w przypadku większości rozwiązań funkcjonalnych, pytanie brzmi, czy kompromis w zakresie wydajności/czytelności jest akceptowalny. Biorąc pod uwagę, jak nieznany byłby Aggregate większości ludzi, łatwo byłoby stwierdzić, że w tym przypadku imperatywne rozwiązanie jest "lepsze" niezależnie od wydajności. – dahlbyk

+0

Po napisaniu go w obie strony, zgadzam się. The Aggregate jest dość tajemniczy, ale jest dobrym narzędziem do umieszczenia w moim pudełku ;-) – Myster

3

Funkcja Kruszywo przyjmuje parametr delegata. Możesz zdefiniować zachowanie, które chcesz zmienić, zmieniając delegata.

var res = data.Aggregate((current, next) => current + ", " + next.Key + ": " + next.Value); 
+6

W przypadku agregacji do typu innego niż źródło należy podać materiał siewny. Określanie "" jako materiału siewnego zostanie skompilowane, ale wynik rozpocznie się od ",". – dahlbyk

4

Agregat posiada 3 przeciążeń, więc można korzystać z jednego, który ma inny typ gromadzić przedmioty, które są wyliczający.

Będziesz musiał podać wartość początkową (twoja niestandardowa klasa) i metodę dodawania scalania nasion z jedną wartością. Przykład:

MyObj[] vals = new [] { new MyObj(1,100), new MyObj(2,200), ... }; 
MySum result = vals.Aggregate<MyObj, MySum>(new MySum(), 
    (sum, val) => 
    { 
     sum.Sum1 += val.V1; 
     sum.Sum2 += val.V2; 
     return sum; 
    }