2010-03-26 16 views
25

Sono un po 'sorpreso di trovare i risultati del seguente codice, dove voglio semplicemente rimuovere tutti 3s da una sequenza di int:LINQ - SkipWhile è rotto?

var sequence = new [] { 1, 1, 2, 3 }; 
var result = sequence.SkipWhile(i => i == 3); // Oh noes! Returns { 1, 1, 2, 3 } 

Perché non è di 3 saltati?

mio pensiero successivo è stato, OK, l'operatore Tranne farà il trucco:

var sequence = new [] { 1, 1, 2, 3 }; 
var result = sequence.Except(i => i == 3); // Oh noes! Returns { 1, 2 } 

In sintesi,

  • Tranne rimuove il 3, ma anche rimuove elementi non distinti. Grr.
  • SkipWhile non salta l'ultimo elemento , anche se corrisponde alla condizione . Grr.

Qualcuno può spiegare perché SkipWhile non salta l'ultimo elemento? E qualcuno può suggerire quale operatore LINQ posso usare per rimuovere il '3' dalla sequenza sopra?

+0

Pensalo come SkipWhile (true). quindi, la prima condizione (i == 3) fallisce. quindi diventa SkipWhile (false) e quindi cosa succede dopo? Restituisce ogni elemento rimanente! –

risposta

51

Non è rotto. SkipWhile salterà solo gli elementi all'inizio del IEnumerable<T>. Una volta che questa condizione non è soddisfatta, prenderà felicemente il resto degli elementi. Altri elementi che in seguito si abbinano alla strada non verranno saltati.

int[] sequence = { 3, 3, 1, 1, 2, 3 }; 
var result = sequence.SkipWhile(i => i == 3); 
// Result: 1, 1, 2, 3 
+0

Ah, ora capisco. Grazie, Ahmad. –

+7

Mi sono appena bruciato perché la documentazione MSDN non lo specifica. cosa dà? http://msdn.microsoft.com/en-us/library/system.linq.enumerable.skipwhile(v=vs.90).aspx –

+6

@StanR. - forse hai bisogno di leggere la documentazione con più attenzione? "Bypassa gli elementi in una sequenza * finché una condizione specificata è vera * *** e restituisce gli elementi rimanenti ***" – JDB

17
var result = sequence.Where(i => i != 3); 
+1

o TakeWhile (i => i! = 3) – Nagg

+9

@Nagg 'TakeWhile' non restituisce nulla in una sequenza iniziata con 3, ad esempio' {3,1,2,3} '. Il risultato desiderato è quello di filtrare tutti i 3, che è ciò che 'Where' è per. –

+0

Uhh, wow, è venerdì, va bene. Dove l'operatore farà il trucco, ovviamente. [Duh]. Tuttavia, non risponde perché SkipWhile non funziona come previsto. –

1

Ahmad già risposto alla tua domanda, ma qui è un'altra opzione:

var result = from i in sequence where i != 3 select i; 
2

Gli operatori SkipWhile e TakeWhile saltare o di ritorno elementi da una sequenza, mentre una funzione predicato passa (restituisce True). Il primo elemento che non supera la funzione di predicato termina il processo di valutazione.

// Ignora gli elementi di una sequenza finché una condizione specificata è vera e restituisce gli elementi rimanenti.

2

Una soluzione che potrebbe risultare utile è utilizzare la funzione Elenco "Trova tutto".

List <int> aggregator = new List<int> { 1, 2, 3, 3, 3, 4 }; 
List<int> result = aggregator.FindAll(b => b != 3);