LINQ onde vs takewhile

99

Eu quero obter uma diferença entre takewhile e onde os métodos LINQ. Eu obtive os seguintes dados do MSDN .Mas não fazia sentido para mim

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

Filtra uma sequência de valores com base em um predicado.

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

Retorna elementos de uma sequência, desde que uma condição especificada seja verdadeira.

Todas as opiniões são bem-vindas.

Mohammed Thabet
fonte
1
Boa pergunta - o Intellisense em TakeWhile ainda diz "Retorna elementos ... contanto que uma condição especificada seja verdadeira". Isso poderia muito bem ser interpretado como o mesmo que um Onde. O texto deve ser algo como "Retorna elementos ... até que a condição seja avaliada como falsa".
Peter

Respostas:

159

TakeWhile para quando a condição é falsa, onde continua e encontra todos os elementos que correspondem à condição

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
Albin Sunnanbo
fonte
30

Where pode examinar toda a sequência em busca de correspondências.

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

TakeWhile para de procurar quando encontra a primeira não correspondência.

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

Digamos que você tenha uma matriz que contém [1, 3, 5, 7, 9, 0, 2, 4, 6, 8]. Agora:

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

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

Jim Mischel
fonte
Acho que whileTest retornará apenas 1 depende das respostas de @David B e @Albin Sunnanbo
Mohammed Thabet
Não, ele retornará itens até que a condição não seja atendida. Nesse caso, 1, 3 e 5 atendem à condição (são <= 5).
Jim Mischel
8

MSDN diz

Enumerable.TakeWhile Method

Retorna os elementos de uma sequência, desde que uma condição especificada seja verdadeira e, a seguir, ignora os elementos restantes.

Enumerable.Where

Filtra uma sequência de valores com base em um predicado.

A diferença é que Enumerable.TakeWhile pula os elementos restantes do primeiro não coincide, quer eles correspondam à condição ou não

naveen
fonte
6

Embora as respostas existentes estejam corretas, nenhuma delas indica por que você deseja usar TakeWhile se os resultados forem os mesmos: Desempenho. Suponha que você tenha uma lista ordenada com 2 bilhões de itens e deseja aqueles que (provavelmente 10 ou 15 itens) têm menos do que um determinado valor. A cláusula Where examinará todos os 2 bilhões de itens, enquanto o TakeWhile irá parar assim que encontrar um valor igual ou superior ao seu valor fornecido

Jmoreno
fonte
5

A ordem da sequência passada é absolutamente crítica com TakeWhile, que terminará assim que um predicado retornar false, enquanto Whereque continuará a avaliar a sequência além do primeiro falsevalor.

Um uso comum de TakeWhileé durante a avaliação preguiçosa de enumeráveis ​​grandes, caros ou até infinitos, onde você pode ter conhecimento adicional sobre a ordem da sequência.

por exemplo, dada a sequência:

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

A .Whereresultará em um loop infinito tentando avaliar parte do enumerável:

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

Considerando que a .TakeWhile, e munido do conhecimento de que os enumeráveis ​​são ascendentes, permitirá que a sequência parcial seja avaliada:

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