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

Dà

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.