LINQ where vs takewhile


99

takewhileとwhere LINQメソッドの違いを取得したい。MSDNから次のデータを取得したが、それは私には意味がなかった

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

述語に基づいて一連の値をフィルタリングします。

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

指定された条件が真である限り、シーケンスから要素を返します。

すべての意見を歓迎します。


1
良い質問-TakeWhileのIntellisenseは、「指定された条件がtrueである限り、要素を返します...」とまだ述べています。これはWhereと同じであると非常によく解釈できます。表現はむしろ、「条件がfalseと評価されるまで要素を返す...」のようなものである必要があります。
ピーター

回答:


159

TakeWhileは、条件がfalseの場合に停止し、Whereは続行して、条件に一致するすべての要素を検索します

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 シーケンス全体を調べて一致を探します。

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

TakeWhile 最初の不一致が発生すると、検索を停止します。

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

9

を含む配列があるとします[1, 3, 5, 7, 9, 0, 2, 4, 6, 8]。今:

var whereTest = array.Where(i => i <= 5);戻り[1, 3, 5, 0, 2, 4]ます。

var whileTest = array.TakeWhile(i => i <= 5);戻り[1, 3, 5]ます。


whileTestは1のみを返すと思いますが、@ David Bと@Albin Sunnanboの回答に依存します
Mohammed Thabet

いいえ、条件が満たされないまでアイテムを返します。この場合、1、3、および5が条件を満たしています(5以下)。
ジムミッシェル、

8

MSDNによると

Enumerable.TakeWhile Method

指定された条件がtrueである限り、シーケンスから要素を返し、残りの要素をスキップします。

Enumerable.Where

述語に基づいて一連の値をフィルタリングします。

違いは、条件に一致するかどうかに関係なく、最初の不一致から残りの要素Enumerable.TakeWhile スキップすることです


6

既存の答えは正しいですが、結果が同じになる場合にTakeWhileを使用する理由を指摘するものはありません。パフォーマンスです。20億個のアイテムを含む順序付きリストがあり、指定された値よりも少ない(おそらく10または15アイテム)リストが必要だとします。Where句は20億項目すべてを検査し、TakeWhileは指定された値以上の値を見つけるとすぐに停止します


5

渡されたシーケンスの順序はで絶対的に重要です。TakeWhile述語がを返すとすぐに終了しますがfalseWhere最初のfalse値を超えてシーケンスを評価し続けます。

の一般的な使用法TakeWhileは、シーケンスの順序に関する追加の知識がある可能性がある、大きい、高価な、または無限の列挙可能なものの遅延評価中です。

例:シーケンスを考える:

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

A .Whereは、列挙可能な要素の一部を評価しようとする無限ループになります。

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

一方、.TakeWhile列挙可能オブジェクトが昇順であるという知識を備えていると、部分シーケンスを評価できます。

var result = InfiniteSequence()
    .TakeWhile(n => n < 100)
    .Count();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.