2013-04-07 6 views
7

Ho una collezione, per esempio:Utilizzando GroupBy e Max in LINQ Lambda Expressions

**id1, id2, value** 
    1 9 12 
    2 9  6 
    3 11 8 
    4 11 87 

voglio usare LINQ e ottenere il seguente risultato:

**value** 
    6 
    87 

P.S.

id1 - select MAX; 
id2 - group column; 

ho bisogno di una risposta in forma di

var result = list.GroupBy(x=>x.id2).select(s=>s.value); 

spero per il vostro aiuto.

+0

Non hanno espresso la tua domanda in modo chiaro a tutti . * Perché * ti aspetteresti che i risultati fossero 6 e 87? Perché stai raggruppando per ID1 quando ogni riga ha un ID1 diverso? Se si stesse raggruppando per id2 ciò avrebbe più senso, ma i risultati dovrebbero essere 12 e 87, non 6 e 87. Si prega di prendere tempo per chiarire la domanda. –

+0

Ma '6 <12' e' 87> 8'; Spiega per favore. –

+0

Penso che voglia raggruppare per id2 e selezionare Valore massimo per ogni gruppo –

risposta

23

EDIT: Okay, ora abbiamo un insieme un po 'più chiara di requisiti (anche se ancora lontano dalla chiaramente scritto) l'approccio più semplice sarebbe probabilmente:

var maxes = list.GroupBy(x => x.id2, 
         (key, xs) => xs.OrderByDescending(x => x.id1) 
             .First() 
             .value); 

Purtroppo LINQ non fornisce un modo semplice di ottenere "l'elemento con il valore massimo" (invece del valore massimo stesso). Ho un metodo in MoreLINQ che fa questo, però, chiamato MaxBy:

var maxes = list.GroupBy(x => x.id2, 
         (key, xs) => xs.MaxBy(x => x.id2).value); 

risposta originale (Raggruppamento per ID2, prendendo il valore massimo)

sto rispondendo assumendo voi in realtà significava raggruppare per id2 anziché id1 e in realtà si desideravano i risultati 12 e 87 anziché 6 e 87. In tal caso, si desidera:

var maxes = list.GroupBy(x => x.id2, (id, xs) => xs.Max(x => x.value)); 

Or (forse più semplice da capire):

var maxes = list.GroupBy(x => x.id2) 
       .Select(xs => xs.Max(x => x.value)); 

Oppure:

var maxes = list.GroupBy(x => x.id2, x => x.value) 
       .Select(values => values.Max()); 

Oppure:

var maxes = list.GroupBy(x => x.id2,  // Key selector 
         x => x.value, // Element selector 
         (key, values) => values.Max()); // Result selector 

O anche:

var maxes = list.GroupBy(x => x.id2) 
       .Select(xs => xs.Select(x => x.value).Max()); 

Come si può vedere, GroupBy ha un sacco di sovraccarichi :)

Oppure si potrebbe usare un'espressione di query:

var maxes = from x in list 
      group x.value by x.id2 into values 
      select values.Max(); 

non ti dovrebbe limitarsi a sia espressioni di query o il metodo di estensione versione - è importante capire entrambi, quindi puoi usare quello che ritieni più appropriato.

+0

id1 - selezionare MAX; id2 - colonna del gruppo; – Pavel

+0

grazie per la tua risposta, ma devo scegliere VALUE per ogni id2 dove id1 - MAX – Pavel

+0

@PavelIvanov: Ok, io * penso * Capisco cosa intendi, ma dovresti davvero fare più sforzi per chiarirlo in futuro. Vedi la mia modifica per una risposta che si spera risolve questo ... –

4

Apparentemente OP vuole la Value con la massima Id1 entro Id2:

dati del campione:

public class Row 
{ 
    public int Id1; 
    public int Id2; 
    public int Value; 
} 

List<Row> rows = new List<Row>(){ 
    new Row(){Id1=1,Id2=9,Value=12}, 
    new Row(){Id1=2,Id2=9,Value=6}, 
    new Row(){Id1=3,Id2=11,Value=8}, 
    new Row(){Id1=4,Id2=11,Value=87} 
}; 

Soluzione:

List<int> res = rows.GroupBy(r => r.Id2) 
        .Select(g => g.OrderByDescending(i=>i.Id1).First().Value) 
        .ToList(); 
0

Nel caso in cui aiuta gli altri, ho avuto una situazione simile, tranne è necessario restituire più record anziché un singolo record.

Es.

**id1, id2, value** 
    1 9 12 
    2 9  6 <- 
    2 9  7 <- 
    3 11 8 
    4 11 87 <- 
    4 11 88 <- 

I seguenti restituisce i suddetti quattro record come due elenchi di due dischi (enumerabili di enumerables):

var maxes = from x in list 
      group x by x.id2 into xs 
      select new {values = xs.Where(x => x.id1 == xs.Max(y => y.id1))}; 

o

var maxes = list.GroupBy(x => x.id2, 
      (key, xs) => new 
      { 
       values = xs.Where(x => x.id1 == xs.Max(y => y.id1)) 
      });