2010-04-23 7 views
5

Ho una lista di elementi e voglio prendereWhile la somma (o qualsiasi aggregazione degli elementi) soddisfa una certa condizione. Il seguente codice fa il lavoro, ma sono abbastanza sicuro che questo non sia un problema insolito per il quale dovrebbe esistere un modello corretto.Linq TakeWhile in base alla somma (o all'aggregato) degli elementi

var list = new List<int> { 1, 2, 3, 4, 5, 6, 7 }; 
int tmp = 0; 
var listWithSum = from x in list 
        let sum = tmp+=x 
        select new {x, sum}; 
int MAX = 10; 
var result = from x in listWithSum 
      where x.sum < MAX 
      select x.x; 

C'è qualcuno che sa come risolvere il compito in modo più bello, probabilmente combinando TakeWhile e si aggregano in una query?

Thx

+0

Sono ben consapevole che non si dovrebbero modificare variabili come effetto collaterale di una query. Se listWithSum viene usato due volte, porterà a risultati diversi se tmp non viene inizializzato in mezzo. Questo è uno dei motivi, perché sono convinto che questa soluzione è cattiva! –

+0

var list = new List {1, 2, 3, 4, 5, 6, 7}; int tmp = 0; int MAX = 10; var result2 = list.TakeWhile (x => { tmp + = x; return tmp

+0

thx Nick. Mentre questa è una versione più breve (e quindi più bella), ha lo stesso problema con un effetto collaterale. –

risposta

2

Mi sembra che si desidera qualcosa come il metodo Scan da Reactive Extensions (la parte System.Interactive) - è come Aggregate, ma produce una successione al posto di un singolo risultato. Si potrebbe poi fare:

var listWithSum = list.Scan(new { Value = 0, Sum = 0 }, 
     (current, next) => new { Value = next, 
            Sum = current.Sum + next }); 

var result = listWithSum.TakeWhile(x => x.Sum < MaxTotal) 
         .Select(x => x.Value); 

(MoreLINQ ha un similar operator, btw - ma attualmente non supporta l'idea della sequenza dell'accumulatore e l'ingresso non essere dello stesso tipo.)

+0

Questa sembra essere una soluzione adeguata, evitando l'effetto collaterale sulla variabile tmp. Non ero a conoscenza di Reactive Extensions. Un altro problema che non ho menzionato sopra è che introducendo il risultato intermedio (il tipo anonimo) il risultato contiene il valore seme dell'aggregato/scansione, che non fa parte dell'elenco iniziale. –

+0

@martinweser: se è necessario saltare il primo risultato, è facile farlo, ma non penso * che sia necessario con Scan. –

Problemi correlati