2009-10-02 77 views
23

我見過的.NET聚合函數的簡單示例工作就像這樣:LINQ的聚集體複合類型爲字符串

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

怎麼可能,如果你想聚合更多複雜「彙總」功能使用類型? 例如:有2種性能如「鍵」和「值」和在類所需的輸出是這樣的:

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

回答

40

有兩個選項:

  1. 項目到string然後骨料:

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

    這具有使用第一string元件作爲種子的優勢(沒有前置的「,」),但會消耗更多的內存用於在此過程中創建的字符串。

  2. 使用接受種子的總超載,也許是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); 
    

    第二委託轉換我們的StringBuilderstring,使用條件修剪出發「」。

+0

完美的,就在我期待的位置,所以我可以從他們的時間開始計時,滾動自己的圈子更快(我的測試周期中只有1或2個項目) – Myster 2009-10-04 21:08:57

+0

列表中的項目很少,與更迫切的解決方案相比,爲Select/Aggregate設置「額外」枚舉器所帶來的性能似乎相當嚴重。與大多數功能解決方案一樣,問題在於性能/可讀性折衷是否可以接受。鑑於不熟悉的Aggregate對於大多數人而言是多麼的容易,很容易得出結論:在這種情況下,必要的解決方案是獨立於性能的「更好」。 – dahlbyk 2009-10-05 01:32:50

+0

寫完之後,我同意。 Aggregate是相當神祕的,但它是一個很好的工具,在我的箱子裏;-) – Myster 2009-10-07 21:01:42

3

聚集函數接受一個代表參數。通過更改委託來定義所需的行爲。

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

如果您要聚合成源以外的類型,則需要指定種子。指定「」作爲種子會編譯,但結果將以「,」開頭。 – dahlbyk 2009-10-02 11:28:41

4

聚合有3個重載,所以你可以使用不同類型的積累你正在枚舉的項目。

您需要傳入種子值(您的自定義類)以及添加合併種子和一個值的方法。例如:

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