2009-11-26 8 views
1

Compte tenu de la structure suivante ...Obtenir la somme d'une valeur dans Linq

class Foo { 

    public string Category { get; set; } 
    public string Code { get; set; } 
    public int Quantity { get; set; } 

} 

Je suis en train d'utiliser LINQ pour résumer une liste de ces objets par catégorie et par code, de sorte que si je fournir les renseignements suivants source ...

List<Foo> foos = new List<Foo>() { 
    new Foo {Category = @"A", Code = @"B", Quantity = 1}, 
    new Foo {Category = @"A", Code = @"B", Quantity = 2}, 
    new Foo {Category = @"C", Code = @"D", Quantity = 3}, 
    new Foo {Category = @"C", Code = @"D", Quantity = 4} 
}; 

je me retrouve avec une liste contenant ...

Foo {Category = @"A", Code = @"B", Quantity = 3}, 
    Foo {Category = @"C", Code = @"D", Quantity = 7} 

(où la quantité est la somme des q d'origine uantités des objets correspondants).

Je sais que j'ai besoin d'utiliser une combinaison de la clause group by et les méthodes d'extension Sum(), je ne semble pas être en mesure de trouver cette combinaison correcte.

S'il vous plaît noter, il n'y a pas de base de données derrière cette liste, je le fais purement avec des objets afin d'extraire la liste d'origine, y compris la somme n'est pas une option.

Merci.

+0

Est-ce objet créé lors de l'exécution ? ou au moment de la compilation comme indiqué ci-dessus? –

Répondre

3
var query = foos 
      .GroupBy(x => new { x.Category, x.Code }) 
      .Select(g => new Foo 
       { 
        Category = g.Key.Category, 
        Code = g.Key.Code, 
        Quantity = g.Sum(x => x.Quantity) 
       }); 
+0

Excellent, j'arrivais juste à cette conclusion basée sur la réponse de Ruben ci-dessus, mais votre réponse me l'a remis sur une plaque. –

+0

Vous n'avez pas besoin d'un appel séparé pour sélectionner ici. GroupBy fait tout ce dont vous avez besoin. –

+0

@Jon: Oui, je me suis rendu compte qu'après que j'avais posté, mais depuis que vous y êtes arrivé en premier, j'ai augmenté votre réponse plutôt que de mettre à jour celle-ci. – LukeH

2

LINQ Merging results in rows est très similaire: -

 var result = foos 
      .GroupBy(foo => new 
      { 
       foo.Category, 
       foo.Code 
      }) 
      .Select(fooGroup => new Foo 
      { 
       Category = fooGroup.Key.Category, 
       Code = fooGroup.Key.Code, 
       Quantity = fooGroup.Sum(foo => foo.Quantity) 
      }); 
+0

En effet le lien était très similaire et utile (+1). J'ai été en mesure d'arriver à la réponse en utilisant ce qui était là et ensuite vérifier par rapport à la réponse de Luke ci-dessous. –

+0

Bonnes choses. Et rappelez-vous, sur SO, ci-dessus et ci-dessous est un concept très transitoire! (BTW, pour les autres ... Mon montage de l'échantillon est arrivé après les réponses de Luke & Jon [mais indépendamment: D]) –

+0

Point pris sur le dessus/ci-dessous - doit essayer et se souvenir de cela! –

10

Vous voulez regrouper à la fois par la catégorie et le code, donc vous voulez un type anonyme pour que - alors que la somme des quantités. Vous pouvez le faire dans un seul appel à GroupBy si vous utilisez le right overload:

var query = list.GroupBy(
    item => new { item.Category, item.Code }, 
    (key, group) => new Foo { Category = key.Category, 
           Code = key.Code, 
           Quantity = group.Sum(x => x.Quantity) }); 

Si vous voulez faire cela avec une expression de requête, vous pouvez utiliser:

var query = from item in list 
      group item by new { item.Category. item.Code } into items 
      select new Foo { Category = items.Key.Category, 
          Code = items.Key.Code, 
          Quantity = items.Sum(x => x.Quantity) }); 
+0

Nice, je ne savais pas celui-là! Et qui aurait pensé qu'on apprendrait quelque chose de FGITWing une petite question LINQ! –

+0

Upvoted pour la clarté pure de la réponse et le fait que vous l'avez fourni dans les deux syntaxes. Je vous remercie. –