Je veux faire une requête avec linq (liste d'objets) et je ne sais vraiment pas comment faire, je peux faire le groupe et la somme mais je ne peux pas sélectionner le reste des champs ..__
ID Value Name Category
1 5 Name1 Category1
1 7 Name1 Category1
2 1 Name2 Category2
3 6 Name3 Category3
3 2 Name3 Category3
Je veux grouper par ID, SUM par valeur et renvoyer tous les champs comme celui-ci.
ID Value Name Category
1 12 Name1 Category1
2 1 Name2 Category2
3 8 Name3 Category3
Mise à jour: Si vous essayez d'éviter le regroupement de tous les champs, vous pouvez grouper simplement par Id
:
data.GroupBy(d => d.Id)
.Select(
g => new
{
Key = g.Key,
Value = g.Sum(s => s.Value),
Name = g.First().Name,
Category = g.First().Category
});
Mais ce code suppose que pour chaque Id
, les mêmes Name
et Category
s'appliquent. Si tel est le cas, vous devriez envisager de normaliser comme le suggère @Aron. Cela impliquerait de conserver Id
et Value
dans une classe et de déplacer Name
, Category
(et tout autre champ qui serait identique pour la même Id
) dans une autre classe, tout en ayant la valeur Id
Le processus de normalisation réduit la redondance et la dépendance des données.
void Main()
{
//Me being lazy in init
var foos = new []
{
new Foo { Id = 1, Value = 5},
new Foo { Id = 1, Value = 7},
new Foo { Id = 2, Value = 1},
new Foo { Id = 3, Value = 6},
new Foo { Id = 3, Value = 2},
};
foreach(var x in foos)
{
x.Name = "Name" + x.Id;
x.Category = "Category" + x.Id;
}
//end init.
var result = from x in foos
group x.Value by new { x.Id, x.Name, x.Category}
into g
select new { g.Key.Id, g.Key.Name, g.Key.Category, Value = g.Sum()};
Console.WriteLine(result);
}
// Define other methods and classes here
public class Foo
{
public int Id {get;set;}
public int Value {get;set;}
public string Name {get;set;}
public string Category {get;set;}
}
essaye ça:
var objList = new List<SampleObject>();
objList.Add(new SampleObject() { ID = 1, Value = 5, Name = "Name1", Category = "Catergory1"});
objList.Add(new SampleObject() { ID = 1, Value = 7, Name = "Name1", Category = "Catergory1"});
objList.Add(new SampleObject() { ID = 2, Value = 1, Name = "Name2", Category = "Catergory2"});
objList.Add(new SampleObject() { ID = 3, Value = 6, Name = "Name3", Category = "Catergory3"});
objList.Add(new SampleObject() { ID = 3, Value = 2, Name = "Name3", Category = "Catergory3"});
var newList = from val in objList
group val by new { val.ID, val.Name, val.Category } into grouped
select new SampleObject() { ID = grouped.ID, Value = grouped.Sum(), Name = grouped.Name, Category = grouped.Category };
vérifier avec LINQPad:
newList.Dump();
Si votre cours est vraiment long et que vous ne voulez pas tout copier, vous pouvez essayer quelque chose comme ça:
l.GroupBy(x => x.id).
Select(x => {
var ret = x.First();
ret.value = x.Sum(xt => xt.value);
return ret;
}).ToList();
Une grande responsabilité vient avec un grand pouvoir. Vous devez être prudent. La ligne ret.value = x.Sum(xt => xt.value)
changera votre collection originale, car vous transmettez une référence, pas un nouvel objet. Si vous voulez l'éviter, vous devez ajouter une méthode Clone
à votre classe telle que MemberwiseClone
(mais là encore, cela créera une copie superficielle, soyez donc prudent). Afer qui vient de remplacer la ligne avec: var ret = x.First().Clone();