two multiple fields columns and c# asp.net linq linq-group

c# - multiple - linq group by count



Seleccione varios campos agrupando por y sumando (4)

Quiero hacer una consulta con linq (lista de objetos) y realmente no sé cómo hacerlo, puedo hacer el grupo y la suma, pero no puedo seleccionar el resto de los campos. Ejemplo:

ID Value Name Category 1 5 Name1 Category1 1 7 Name1 Category1 2 1 Name2 Category2 3 6 Name3 Category3 3 2 Name3 Category3

Quiero agrupar por ID, SUM por valor y devolver todos los campos como este.

ID Value Name Category 1 12 Name1 Category1 2 1 Name2 Category2 3 8 Name3 Category3


Actualizado: si está intentando evitar agrupar para todos los campos, puede agrupar solo por 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 });

Pero este código supone que para cada Id , se aplican el mismo Name y Category . Si es así, debería considerar la normalización como sugiere @Aron. Implicaría mantener la Id y el Value en una clase y mover el Name , la Category (y cualquiera de los otros campos serían los mismos para la misma Id ) a otra clase, mientras que también tiene la Id como referencia. El proceso de normalización reduce la redundancia y la dependencia de los datos.


Si tu clase es realmente larga y no quieres copiar todas las cosas, puedes intentar algo como esto:

l.GroupBy(x => x.id). Select(x => { var ret = x.First(); ret.value = x.Sum(xt => xt.value); return ret; }).ToList();

Con gran poder viene la gran responsabilidad. Necesitas tener cuidado. La línea ret.value = x.Sum(xt => xt.value) cambiará su colección original, ya que está pasando una referencia, no un nuevo objeto. Si desea evitarlo, debe agregar algún método de Clone en su clase como MemberwiseClone (pero, de nuevo, esto creará una copia superficial, así que tenga cuidado). Después de eso solo reemplace la línea con: var ret = x.First().Clone();


prueba esto:

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

Para consultar con LINQPad:

newList.Dump();


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