LINQ dove vs prendere mentre


99

Voglio ottenere una differenza tra i metodi take while e where LINQ. Ho ottenuto i seguenti dati da MSDN .Ma per me non aveva senso

Where<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>) 

Filtra una sequenza di valori in base a un predicato.

TakeWhile<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

Restituisce elementi da una sequenza purché una condizione specificata sia vera.

Tutte le opinioni sono benvenute.


1
Bella domanda: Intellisense su TakeWhile dice ancora "Restituisce elementi ... fintanto che una condizione specificata è vera". Questo potrebbe benissimo essere interpretato come lo stesso di un Where. La formulazione dovrebbe piuttosto essere qualcosa come "Restituisce elementi ... finché la condizione non viene valutata come falsa".
Peter il

Risposte:


159

TakeWhile si ferma quando la condizione è falsa, Where continua e trova tutti gli elementi che corrispondono alla condizione

var intList = new int[] { 1, 2, 3, 4, 5, -1, -2 };
Console.WriteLine("Where");
foreach (var i in intList.Where(x => x <= 3))
    Console.WriteLine(i);
Console.WriteLine("TakeWhile");
foreach (var i in intList.TakeWhile(x => x <= 3))
    Console.WriteLine(i);

Where
1
2
3
-1
-2
TakeWhile
1
2
3

30

Where può esaminare l'intera sequenza alla ricerca di corrispondenze.

Enumerable.Range(1, 10).Where(x => x % 2 == 1)
// 1, 3, 5, 7, 9

TakeWhile smette di cercare quando incontra la prima non corrispondenza.

Enumerable.Range(1, 10).TakeWhile(x => x % 2 == 1)
// 1

9

Supponi di avere un array che contiene [1, 3, 5, 7, 9, 0, 2, 4, 6, 8]. Adesso:

var whereTest = array.Where(i => i <= 5);tornerà [1, 3, 5, 0, 2, 4].

var whileTest = array.TakeWhile(i => i <= 5);tornerà [1, 3, 5].


Penso che whileTest tornerà solo 1 dipende dalle risposte di @David B e @Albin Sunnanbo
Mohammed Thabet

No, restituirà gli articoli fino a quando la condizione non sarà soddisfatta. In questo caso, 1, 3 e 5 soddisfano la condizione (sono <= 5).
Jim Mischel

8

Dice MSDN

Enumerable.TakeWhile Method

Restituisce elementi da una sequenza purché una condizione specificata sia vera, quindi ignora gli elementi rimanenti.

Enumerable.Where

Filtra una sequenza di valori in base a un predicato.

La differenza è che Enumerable.TakeWhile salta gli elementi rimanenti dalla prima non corrispondenza indipendentemente dal fatto che corrispondano o meno alla condizione


6

Sebbene le risposte esistenti siano corrette, nessuna di esse indica perché vorresti utilizzare TakeWhile se i risultati fossero gli stessi: Performance. Supponiamo di avere un elenco ordinato con 2 miliardi di elementi e di volere quelli che (probabilmente 10 o 15 elementi) sono inferiori a un dato valore. La clausola Where esaminerà tutti i 2 miliardi di elementi, mentre TakeWhile si fermerà non appena troverà un valore uguale o superiore al valore fornito


5

L'ordine della sequenza passata è assolutamente critico con TakeWhile, che terminerà non appena ritorna un predicato false, mentre Wherecontinuerà a valutare la sequenza oltre il primo falsevalore.

Un utilizzo comune di TakeWhileè durante la valutazione pigra di enumerabili grandi, costosi o persino infiniti in cui è possibile avere ulteriori conoscenze sull'ordinamento della sequenza.

ad es. data la sequenza:

IEnumerable<BigInteger> InfiniteSequence()
{
    BigInteger sequence = 0;
    while (true)
    {
        yield return sequence++;
    }
}

A .Whererisulterà in un ciclo infinito che cerca di valutare parte dell'enumerabile:

var result = InfiniteSequence()
    .Where(n => n < 100)
    .Count();

Mentre a .TakeWhile, e armato della consapevolezza che gli enumerabili sono ascendenti, consentirà di valutare la sequenza parziale:

var result = InfiniteSequence()
    .TakeWhile(n => n < 100)
    .Count();
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.