This article has been localized into Portuguese by the community.
Filtrando dados: O método Where()
Uma das operações mais básicas (mas também mais poderosas) que você pode executar em um conjunto de dados é filtrar algumas delas. Nós já vimos um vislumbre do que você pode fazer com o método Where() no artigo de introdução do LINQ, mas neste artigo, vamos nos aprofundar um pouco mais. Nós já discutimos quantos métodos LINQ podem usar uma Expressão Lambda para executar sua tarefa e o método Where() é um deles - ela irá fornecer cada item como entrada e então você fornecerá a lógica que decide se o item é ou não included (return true) ou excluded (return false) do resultado final. Aqui está um exemplo básico:
List<int> numbers = new List<int>()
{
1, 2, 4, 8, 16, 32
};
var smallNumbers = numbers.Where(n => n < 10);
foreach (var n in smallNumbers)
Console.WriteLine(n);
Neste exemplo, cada número é verificado em relação à nossa expressão, que retornará verdadeiro se o número for menor que 10 e falso se for 10 ou maior. Como resultado, obtemos uma versão da lista original, onde incluímos apenas números abaixo de 10, que são então enviados para o console.
Mas a expressão não precisa ser tão simples assim - podemos facilmente adicionar mais requisitos a ela, assim como se fosse uma declaração if regular:
List<int> numbers = new List<int>()
{
1, 2, 4, 8, 16, 32
};
var smallNumbers = numbers.Where(n => n > 1 && n != 4 && n < 10);
foreach (var n in smallNumbers)
Console.WriteLine(n);
Especificamos que o número deve ser maior que 1, mas não o número específico 4 e menor que 10.
É claro que você também pode usar vários métodos em sua expressão - desde que o resultado final seja um valor booleano, de modo que o método Where() saiba se você deseja ou não incluir o item em questão, é bom ir. Aqui está um exemplo:
List<int> numbers = new List<int>()
{
1, 2, 4, 7, 8, 16, 29, 32, 64, 128
};
List<int> excludedNumbers = new List<int>()
{
7, 29
};
var validNumbers = numbers.Where(n => !excludedNumbers.Contains(n));
foreach (var n in validNumbers)
Console.WriteLine(n);
Neste exemplo, declaramos uma segunda lista de números - uma espécie de lista negra de números que não queremos incluir! No método Where(), usamos o método Contains() na lista negra, para decidir se um número pode ser incluído na lista final de números ou não.
E, claro, funciona para objetos mais complexos que números e strings, e ainda é muito fácil de usar. Basta dar uma olhada neste exemplo, em que usamos objetos com informações do usuário em vez de números e usamos o método Where() para obter uma lista de usuários com nomes começando com a letra "J", com 39 anos ou menos:
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinqWhere2
{
class Program
{
static void Main(string[] args)
{
List<User> listOfUsers = new List<User>()
{
new User() { Name = "John Doe", Age = 42 },
new User() { Name = "Jane Doe", Age = 34 },
new User() { Name = "Joe Doe", Age = 8 },
new User() { Name = "Another Doe", Age = 15 },
};
var filteredUsers = listOfUsers.Where(user => user.Name.StartsWith("J") && user.Age < 40);
foreach (User user in filteredUsers)
Console.WriteLine(user.Name + ": " + user.Age);
}
class User
{
public string Name { get; set; }
public int Age { get; set; }
}
}
}
E apenas para comparação, aqui está como seria a operação where se tivéssemos usado a sintaxe baseada em consulta em vez do método baseado:
// Method syntax
var filteredUsers = listOfUsers.Where(user => user.Name.StartsWith("J") && user.Age < 40);
// Query syntax
var filteredUsersQ = from user in listOfUsers where user.Name.StartsWith("J") && user.Age < 40 select user;
Encadeando vários métodos Where()
Discutimos isso brevemente na introdução ao LINQ: O resultado real de uma expressão LINQ não é percebido até que você realmente precise dos dados, por exemplo, quando você passar por cima, conte ou iteração (como fazemos em nossos exemplos). Isso também significa que você encadeia vários métodos Where() juntos, se achar que é mais fácil de ler - em expressões muito complexas, definitivamente pode ser! Aqui está uma versão modificada do nosso exemplo anterior:
List<int> numbers = new List<int>()
{
1, 2, 4, 8, 16, 32
};
var smallNumbers = numbers.Where(n => n > 1).Where(n => n != 4).Where(n => n < 10);
foreach (var n in smallNumbers)
Console.WriteLine(n);
O resultado é exatamente o mesmo e, embora a primeira versão possa não ter sido complexa o suficiente para justificar a divisão em várias chamadas de método Where(), você provavelmente se deparará com situações em que faz sentido fazer isso. Quero enfatizar que isso não custa extra, em termos de desempenho, porque a (s) operação (ões) real (ais) não são executadas até a parte em que fazemos o loop sobre o resultado - então, o compilador e o interpretador terão otimizou sua consulta para ser o mais rápido possível, independentemente de como você a escreveu.
Resumo
Com o método Where() , você pode filtrar facilmente itens indesejados da sua fonte de dados para criar um subconjunto dos dados originais. Lembre-se de que, de fato, é um novo conjunto de dados que você obtém - a fonte de dados original não será alterada, a menos que você substitua especificamente a variável original.