Agrupando Listas en Memoria en C# con LINQ y Expresiones Lambda

Al trabajar con listas en C#, puede que te encuentres con diversos escenarios donde necesites agrupar elementos basándote en una propiedad específica. Por ejemplo, supongamos que tienes una colección de objetos Foo, y deseas organizarlos según los valores de sus propiedades Bar. Aquí es donde entra en juego el poder de LINQ (Language Integrated Query) y las expresiones lambda. En esta publicación del blog, exploraremos cómo agrupar listas en memoria usando estas características de C# de manera efectiva.

Entendiendo el Problema

Imagina que tienes una lista de objetos Foo, donde cada Foo tiene propiedades Bar y Lum. Algunas instancias de Foo pueden compartir el mismo valor para Bar. Tu objetivo es agrupar estas instancias de Foo por sus valores de Bar y luego iterar sobre las colecciones agrupadas para acceder a sus correspondientes valores de Lum. Esto puede mejorar la organización de datos y facilitar la manipulación de conjuntos de datos específicos.

Ejemplo de Escenario

Consideremos un ejemplo específico con la siguiente lista de instancias de Foo:

var foos = new List<Foo> {
   new Foo{Bar = 1,Lum = 1},
   new Foo{Bar = 1,Lum = 2},
   new Foo{Bar = 2,Lum = 3},
};

Resultado Deseado

Queremos agrupar estas instancias de Foo por sus valores de Bar, produciendo algo como:

  • Para Bar = 1: Lum = 1, Lum = 2
  • Para Bar = 2: Lum = 3

Solución Usando LINQ

Puedes agrupar los objetos Foo utilizando la cláusula group by de LINQ. Aquí te mostramos cómo se puede lograr:

var groupedFoos = from foo in foos
                  group foo by foo.Bar into grouped
                  let lums = from g in grouped
                             select g.Lum
                  select new { Bar = grouped.Key, Lums = lums };

Pasos Explicados

  • Group By: La parte group foo by foo.Bar agrupa las instancias de Foo basándose en la propiedad Bar.
  • Into Grouped: Esto crea un nuevo ámbito para cada grupo.
  • Seleccionando Valores de Lum: La declaración let lums te permite crear una nueva colección que consiste en valores de Lum de los objetos agrupados.
  • Selección Final: La selección final ensambla todo en un nuevo objeto que contiene el valor de Bar y su correspondiente lista de valores de Lum.

Solución Usando Expresiones Lambda

Alternativamente, puedes lograr el mismo resultado usando expresiones lambda, que pueden ofrecer una sintaxis más concisa. Aquí te mostramos cómo:

var groupedFoos = foos.GroupBy(x => x.Bar)
                      .Select(y => new { Bar = y.Key, Lums = y.Select(z => z.Lum) });

Cómo Funciona

  • GroupBy: Este método toma una función lambda para especificar la propiedad por la cual queremos agrupar, a saber x.Bar.
  • Select: Después de agrupar, utilizamos Select para crear un nuevo objeto anónimo para cada grupo, que contiene los valores de Bar y los correspondientes valores de Lum.

Iterando a Través de Datos Agrupados

Independientemente de si utilizas LINQ o expresiones lambda, iterar a través de los datos agrupados permanece igual. Puedes recorrer cada grupo y imprimir los valores de Lum de la siguiente manera:

foreach (var group in groupedFoos)
{
    Console.WriteLine("Lums para Bar#" + group.Bar);
    foreach (var lum in group.Lums)
    {
        Console.WriteLine(lum);
    }
}

La Salida será:

Lums para Bar#1
1
2
Lums para Bar#2
3

Conclusión

Agrupar listas en memoria utilizando LINQ o expresiones lambda en C# es una forma poderosa de organizar tus datos. Ya sea que prefieras la legibilidad de la sintaxis de LINQ o la concisión de las expresiones lambda, ambos enfoques te permitirán lograr la agrupación deseada de tus datos de manera efectiva.

Para aquellos que buscan profundizar su comprensión de LINQ, considera explorar 101 Muestras de LINQ para más ejemplos comprensivos.

Si tienes alguna pregunta o quisieras compartir tus experiencias sobre la agrupación de datos en C#, ¡no dudes en dejar un comentario abajo!