LINQ wo vs nehmen

99

Ich möchte einen Unterschied zwischen der Dauer und den LINQ-Methoden machen. Ich habe die folgenden Daten von MSDN erhalten. Aber es hat für mich keinen Sinn ergeben

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

Filtert eine Folge von Werten basierend auf einem Prädikat.

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

Gibt Elemente aus einer Sequenz zurück, solange eine bestimmte Bedingung erfüllt ist.

Alle Meinungen sind willkommen.

Mohammed Thabet
quelle
1
Gute Frage - der Intellisense auf TakeWhile sagt immer noch "Gibt Elemente zurück ... solange eine bestimmte Bedingung erfüllt ist". Dies könnte sehr gut als dasselbe wie ein Wo interpretiert werden. Der Wortlaut sollte eher so lauten wie "Gibt Elemente zurück ... bis die Bedingung als falsch ausgewertet wird".
Peter

Antworten:

159

TakeWhile stoppt, wenn die Bedingung falsch ist. Where fährt fort und findet alle Elemente, die der Bedingung entsprechen

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

Gibt

Where
1
2
3
-1
-2
TakeWhile
1
2
3
Albin Sunnanbo
quelle
30

Where kann die gesamte Sequenz auf Übereinstimmungen untersuchen.

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

TakeWhile hört auf zu suchen, wenn es auf das erste Nicht-Match stößt.

Enumerable.Range(1, 10).TakeWhile(x => x % 2 == 1)
// 1
Amy B.
quelle
9

Angenommen, Sie haben ein Array, das enthält [1, 3, 5, 7, 9, 0, 2, 4, 6, 8]. Jetzt:

var whereTest = array.Where(i => i <= 5);wird zurückkehren [1, 3, 5, 0, 2, 4].

var whileTest = array.TakeWhile(i => i <= 5);wird zurückkehren [1, 3, 5].

Jim Mischel
quelle
Ich denke, währendTest nur 1 zurückgeben wird, hängt von @David B und @Albin Sunnanbo Antworten ab
Mohammed Thabet
Nein, es werden Elemente zurückgegeben, bis die Bedingung nicht erfüllt ist. In diesem Fall erfüllen 1, 3 und 5 die Bedingung (sie sind <= 5).
Jim Mischel
8

MSDN sagt

Enumerable.TakeWhile Method

Gibt Elemente aus einer Sequenz zurück, solange eine bestimmte Bedingung erfüllt ist, und überspringt dann die verbleibenden Elemente.

Enumerable.Where

Filtert eine Folge von Werten basierend auf einem Prädikat.

Der Unterschied besteht darin, dass Enumerable.TakeWhile die verbleibenden Elemente aus der ersten Nichtübereinstimmung übersprungen werden, unabhängig davon, ob sie der Bedingung entsprechen oder nicht

Naveen
quelle
6

Obwohl die vorhandenen Antworten korrekt sind, weist keine darauf hin, warum Sie TakeWhile verwenden möchten, wenn die Ergebnisse dieselben wären: Leistung. Angenommen, Sie haben eine geordnete Liste mit 2 Milliarden Artikeln und möchten diejenigen, die (wahrscheinlich 10 oder 15 Artikel) weniger als einen bestimmten Wert haben. Die Where-Klausel prüft alle 2 Milliarden Elemente, während TakeWhile beendet wird, sobald ein Wert gefunden wird, der gleich oder größer als Ihr angegebener Wert ist

jmoreno
quelle
5

Die Reihenfolge der übergebenen Sequenz ist absolut kritisch mit TakeWhile, was endet, sobald ein Prädikat zurückkehrt false, während Wheredie Sequenz weiterhin über den ersten falseWert hinaus ausgewertet wird.

Eine häufige Verwendung für TakeWhileist die verzögerte Auswertung großer, teurer oder sogar unendlicher Aufzählungen, bei denen Sie möglicherweise zusätzliche Kenntnisse über die Reihenfolge der Sequenz haben.

zB Gegeben die Reihenfolge:

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

A .Whereführt zu einer Endlosschleife, die versucht, einen Teil der Aufzählung auszuwerten:

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

Während a .TakeWhileund mit dem Wissen, dass die Aufzählungen aufsteigend sind, die Bewertung der Teilsequenz ermöglicht:

var result = InfiniteSequence()
    .TakeWhile(n => n < 100)
    .Count();
StuartLC
quelle