LINQ où vs prendre pendant

99

Je veux faire la différence entre les méthodes take while et where LINQ. J'ai obtenu les données suivantes de MSDN. Mais cela n'a pas de sens pour moi

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

Filtre une séquence de valeurs basée sur un prédicat.

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

Renvoie des éléments d'une séquence tant qu'une condition spécifiée est vraie.

Toutes les opinions sont les bienvenues.

Mohammed Thabet
la source
1
Bonne question - l'Intellisense sur TakeWhile dit toujours "Renvoie des éléments ... tant qu'une condition spécifiée est vraie". Cela pourrait très bien être interprété comme étant la même chose qu'un Where. Le libellé devrait plutôt être quelque chose comme "Renvoie des éléments ... jusqu'à ce que la condition soit évaluée comme fausse".
Peter

Réponses:

159

TakeWhile s'arrête lorsque la condition est fausse, Where continue et trouve tous les éléments correspondant à la condition

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

Donne

Where
1
2
3
-1
-2
TakeWhile
1
2
3
Albin Sunnanbo
la source
30

Where peut examiner toute la séquence à la recherche de correspondances.

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

TakeWhile arrête de regarder quand il rencontre le premier non-match.

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

Disons que vous avez un tableau qui contient [1, 3, 5, 7, 9, 0, 2, 4, 6, 8]. Maintenant:

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

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

Jim Mischel
la source
Je pense que whileTest ne retournera que 1 dépend des réponses @David B et @Albin Sunnanbo
Mohammed Thabet
Non, il renverra les articles jusqu'à ce que la condition ne soit pas remplie. Dans ce cas, 1, 3 et 5 remplissent la condition (ils sont <= 5).
Jim Mischel
8

MSDN dit

Enumerable.TakeWhile Method

Renvoie les éléments d'une séquence tant qu'une condition spécifiée est vraie, puis ignore les éléments restants.

Enumerable.Where

Filtre une séquence de valeurs basée sur un prédicat.

La différence est que Enumerable.TakeWhile ignore les éléments restants de la première non-correspondance, qu'ils correspondent ou non à la condition

Naveen
la source
6

Bien que les réponses existantes soient correctes, aucune d'entre elles n'indique pourquoi vous voudriez utiliser TakeWhile si les résultats seraient les mêmes: Performance. Supposons que vous ayez une liste ordonnée contenant 2 milliards d'éléments et que vous souhaitiez ceux qui (probablement 10 ou 15 éléments) sont inférieurs à une valeur donnée. La clause Where examinera les 2 milliards d'articles, tandis que TakeWhile s'arrêtera dès qu'il trouvera une valeur égale ou supérieure à la valeur fournie

jmoreno
la source
5

L'ordre de la séquence passée est absolument critique avec TakeWhile, qui se terminera dès le retour d'un prédicat false, alors que Wherecontinuera à évaluer la séquence au-delà de la première falsevaleur.

Une utilisation courante de TakeWhileest lors de l'évaluation paresseuse d'énumérables volumineux, coûteux ou même infinis où vous pouvez avoir des connaissances supplémentaires sur l'ordre de la séquence.

Par exemple, étant donné la séquence:

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

A .Whereentraînera une boucle infinie essayant d'évaluer une partie de l'énumérable:

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

Alors que a .TakeWhile, et armé de la connaissance que les énumérables sont ascendants, permettra d'évaluer la séquence partielle:

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