2014-04-15 54 views
3

我有一個IEnumerable<IEnumerable<double>>它基本上可以認爲是雙打的二維數組,我希望做的就是一維數組(或列表或其他)什麼是總的所有列我原來的收藏。換句話說,如果我有:總和列

1 2 3 4 
2 3 1 6 
3 4 5 6 
------------- 
6 9 9 16 

我想最後一行(顯然不是原始集合的一部分)。

有一個簡單的方法使用LINQ做到這一點,這樣我就不必遍歷整個事情?我知道我可以使用.Sum共計一行或一列,但我想累計每一行。

我見過使用group暗示一些其他的問題(主要是處理數據庫查詢),但似乎並沒有爲我工作。我試過這個:

  var totals = from p in toTotal 
         group p by 1 into g 
         select g.Sum(t => t.First()); 

但這只是總結一切。

有一個聰明的辦法做到這一點?

編輯:例如,如果toTotal被定義爲:

List<List<double>> toTotal = new List<List<double>>() { 
     new List<double> {1, 2, 3, 4}, 
     new List<double> {2, 3 , 1, 6}, 
     new List<double> {3 , 4, 5 , 6} 
    }; 

回答

3

確定。我想,我已經打了它:

var totals = toTotal.Aggregate((prev, next) => prev.Zip(next, (a, b) => a + b)); 

訣竅是,我一直在尋找一個Fold(或Reduce)功能,但在LINQ它被稱爲Aggregate

下面是示出該一個fiddle和@ Habib的用於合計行(用於比較)的代碼。從我這裏唯一的變化(我是用我的實際代碼是什麼)是我需要.ToList.Zip的結果,因爲這個測試情況下,我有一個List<List<double>>這似乎如果不打亂編譯器顯式轉換爲列表。在我的實際代碼toTotalIEnumerable<IEnumerable<double>>,不需要轉換。

3

編輯:

你可以做:

List<List<double>> toTotal = new List<List<double>>() { 
new List<double> {1, 2, 3, 4}, 
new List<double> {2, 3 , 1, 6}, 
new List<double> {3 , 4, 5 , 6} 
           }; 

var res = toTotal.Select(r => r.Select((t, i) => new { Column = i, Value = t })) 
       .SelectMany(r => r) 
       .GroupBy(r => r.Column) 
       .Select(grp => new 
       { 
        Column = grp.Key, 
        Sum = grp.Select(r => r.Value).Sum(), 
       }); 

foreach (var item in res) 
{ 
    Console.WriteLine("Column: {0}, Sum: {1}", item.Column, item.Sum); 
} 

,您將得到:

Column: 0, Sum: 6 
Column: 1, Sum: 9 
Column: 2, Sum: 9 
Column: 3, Sum: 16 

老回答

您需要Sum爲您的IEnumerable toTotal的每一個元素,你可以把它想:

double[]totals = toTotal.Select(r => r.Sum()).ToArray(); 
+0

謝謝,但那不是我正在尋找的。這將總計行數,而不是列數。我需要'r [0],r [1] ... r [n]' –

+0

@MattBurland的總和,你能告訴我們如何用某些值定義'toTotal'。 – Habib

+1

@MattBurland,剛剛修改了我的答案,現在正在對專欄進行總結。但我必須承認你的答案看起來很優雅。 – Habib