2011-04-07 7 views
2

J'ai une simple question LINQ:Agrégation de composés LINQ

J'ai une collection de FooBars. Un Foobar a une propriété foo et une propriété de bar. Je veux agréger à la fois foo et la barre sans courir à travers ma collection de foobars plus d'une fois.

Ie. Je veux quelque chose d'équivalent à SQL:

SELECT SUM(Foo), SUM(Bar) From FooBars 

ou

int fooSum, barSum; 
foreach (var foobar in foobars) 
{ 
    fooSum += foobar.Foo; 
    barSum += foobar.Bar; 
} 

Y at-il une façon élégante d'écrire ce avec un composé de sélectionner (ou similaire) dans LINQ?

Répondre

4

Vous pouvez utiliser Aggregate, en conservant les totaux cumulés dans un type ou un tuple anonyme. Bien que je voudrais probablement aller avec une boucle simple moi-même.

var result = foobars.Aggregate(new { FooSum = 0, BarSum = 0 }, 
           (a, x) => new { 
               FooSum = a.FooSum + x.Foo, 
               BarSum = a.BarSum + x.Bar 
              }); 

Console.WriteLine("FooSum=" + result.FooSum + ", BarSum=" + result.BarSum); 
+0

Juste ce que je cherchais. Merci. – Holstebroe

+0

@LukeH: cela ne va-t-il pas créer un gros overhead d'objet quand 'foobars' contient beaucoup d'éléments, parce que vous créez une nouvelle instance du type anonyme pour chaque itération? –

+0

@Daniel: Oui, en effet, et la même chose s'appliquerait si vous utilisiez aussi quelque chose comme 'Tuple ' car ce sont aussi des types ref. Je suppose que vous pourriez créer une structure personnalisée pour faire le travail, ou (mal) utiliser une structure intégrée comme 'KeyValuePair '. Je suppose que vous pourriez également utiliser quelque chose comme 'int [2]' comme accumulateur et le faire muter à chaque itération. Avec ces suggestions, ça devient * vraiment * moche, une boucle 'foreach' est définitivement la meilleure option. – LukeH