Come ottenere il primo record in ciascun gruppo usando Linq


133

Considerando i seguenti record:

   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

Voglio raggruppare in base al F1campo e ordinare per Ide ottenere tutti i campi dal primo record del gruppo simili a questi record:

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

Come posso fare questo usando Linq?

Risposte:


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

4
Sono contento di averlo trovato. Ho ricevuto il messaggio di errore "Il metodo 'First' può essere utilizzato solo come operazione di query finale. In questa istanza, invece, considerare l'utilizzo del metodo 'FirstOrDefault'." dal tuo esempio. Solo l'operazione sulla lista che ho fatto dopo che la query stava passando myResult.ToList () a un metodo. L'utilizzo di FirstOrDefault ha risolto il problema
aghost il

Sarebbe OrderBy(p => p.Id), lo volevano ordinato per ID non per la colonna dell'anno.
Mike Flynn,

Potete per favore provider di qualche aiuto per questo: stackoverflow.com/questions/44764687/...
Si8

Cosa succede se si desidera recuperare il primo e l'ultimo elemento dal gruppo?
Sandeep Pandey,

176
var result = input.GroupBy(x=>x.F1,(key,g)=>g.OrderBy(e=>e.F2).First());

2
Questo mi ha mostrato come usare la sintassi Fluent. I sovraccarichi di GroupBy sembrano darti molta potenza, uno da aggiungere alla lunga lista di apprendimento!
rogersillito,

1
@rogersillito ecco perché si chiama query (Language Integrated Query - LINQ), anche GroupBy ha molti sovraccarichi ma ce ne sono solo alcuni comunemente usati, dipende anche dalle preferenze personali, come alcuni preferiscono scriverlo come .GroupBy(x=>x.F1).Select(g=>...), può sembrare più facile da capire.
King King,

11
Dovresti sostituirlo .First()con .FirstOrDefault()o otterrai l'eccezione:The method 'First' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
Nikolay Kostov,

5
@NikolayKostov Lo so, ma ho ipotizzato che LINQ qui sia usato come LINQ-to-object, non LINQ-to-entity, quindi possiamo tranquillamente usarlo .First(). La domanda del PO sembra davvero preoccuparsi solo di linq-to-object, sebbene abbia anche taggato la domanda con linq-to-entities(non sono sicuro di aver capito di cosa si tratta).
King King,

1
Mi è piaciuta questa risposta, bella.
Ajas Aju,

8

Il tendalino di @Alireza è del tutto corretto, ma è necessario notare che quando si utilizza questo codice

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

che è simile a questo codice perché ordini la lista e poi esegui il raggruppamento in modo da ottenere la prima fila di gruppi

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

Ora se vuoi fare qualcosa di più complesso come prendere lo stesso risultato di raggruppamento ma prendere il primo elemento di F2 e l'ultimo elemento di F3 o qualcosa di più personalizzato, puoi farlo studiando il codice qui sotto

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

Quindi otterrai qualcosa del genere

   F1            F2             F3 
 -----------------------------------
   Nima          1990           12
   John          2001           2
   Sara          2010           4

1
Il delimitatore o il separatore del nuovo oggetto deve essere una virgola non un punto e virgola. Verificare.
Naredla Nithesh Reddy,

3

Usalo per ottenere quello che vuoi. Quindi decidere quali proprietà si desidera restituire.

yourList.OrderBy(l => l.Id).GroupBy(l => new { GroupName = l.F1}).Select(r => r.Key.GroupName)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.