Cómo obtener el primer registro en cada grupo usando Linq

133

Considerando los siguientes registros:

   Id          F1            F2             F3 
 -------------------------------------------------
   1           Nima          1990           10
   2           Nima          1990           11
   3           Nima          2000           12
   4           John          2001           1
   5           John          2002           2 
   6           Sara          2010           4

Quiero agrupar según el F1campo y ordenar Idy obtener todos los campos del primer registro de grupo similar a estos registros:

   Id          F1            F2             F3 
 -------------------------------------------------
   1           Nima          1990           10
   4           John          2001           1
   6           Sara          2010           4

¿Cómo puedo hacer esto usando linq?

arriano
fuente

Respuestas:

127
    var res = from element in list
              group element by element.F1
                  into groups
                  select groups.OrderBy(p => p.F2).First();
Alireza
fuente
44
Me alegro de haber encontrado esto. Recibí el mensaje de error "El método 'Primero' solo se puede usar como una operación de consulta final. Considere usar el método 'FirstOrDefault' en este caso en su lugar". de tu ejemplo La única operación en la lista que hice después de la consulta fue pasar myResult.ToList () a un método. Usando FirstOrDefault lo resolvió aunque
AgHost
Sería OrderBy(p => p.Id), querían que se ordenara por ID, no por la columna del año.
Mike Flynn
Puede usted por favor proveedor de alguna ayuda para esto: stackoverflow.com/questions/44764687/...
Si8
¿Qué sucede si desea recuperar el primer y el último elemento del grupo?
Sandeep Pandey
176
var result = input.GroupBy(x=>x.F1,(key,g)=>g.OrderBy(e=>e.F2).First());
Rey rey
fuente
2
Esto me mostró el camino usando la sintaxis fluida. Las sobrecargas de GroupBy parecen darle mucho poder, ¡uno para agregar a la larga lista de aprendizaje!
rogersillito
1
@rogersillito es por eso que se llama una consulta (Language Integrated Query - LINQ), también GroupBy tiene muchas sobrecargas, pero solo se usan unas pocas, también depende de la preferencia personal, ya que algunos prefieren escribirlo como .GroupBy(x=>x.F1).Select(g=>...), Puede parecer más fácil de entender.
Rey Rey
11
Debe reemplazar .First()con .FirstOrDefault()u obtendrá la excepción:The method 'First' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
Nikolay Kostov
55
@NikolayKostov Sé sobre eso, pero asumí que el LINQ aquí se usa como LINQ-to-object, no LINQ-to-persons, por lo que podemos usarlo de manera segura .First(). La pregunta del OP parece realmente preocuparse por linq-to-object, aunque también etiquetó la pregunta con linq-to-entities(no estoy seguro de si entendió qué es eso).
Rey Rey
1
Me gustaron estas respuestas, una buena.
Ajas Aju
8

El principio de @Alireza es totalmente correcto, pero debe tener en cuenta que al usar este código

var res = from element in list
          group element by element.F1
              into groups
              select groups.OrderBy(p => p.F2).First();

que es similar a este código porque ordenas la lista y luego haces la agrupación para obtener la primera fila de grupos

var res = (from element in list)
          .OrderBy(x => x.F2)
          .GroupBy(x => x.F1)
          .Select()

Ahora, si desea hacer algo más complejo como tomar el mismo resultado de agrupación pero tomar el primer elemento de F2 y el último elemento de F3 o algo más personalizado, puede hacerlo estudiando el código a continuación

 var res = (from element in list)
          .GroupBy(x => x.F1)
          .Select(y => new
           {
             F1 = y.FirstOrDefault().F1;
             F2 = y.First().F2;
             F3 = y.Last().F3;
           });

Entonces obtendrás algo como

   F1            F2             F3 
 -----------------------------------
   Nima          1990           12
   John          2001           2
   Sara          2010           4
Stavros Koureas
fuente
1
El delimitador o separador del nuevo objeto debe ser una coma, no dos puntos. Verifique.
Naredla Nithesh Reddy
3

Úselo para lograr lo que quiere. Luego, decida qué propiedades desea devolver.

yourList.OrderBy(l => l.Id).GroupBy(l => new { GroupName = l.F1}).Select(r => r.Key.GroupName)
Rubens Mussi Cury
fuente