CodeGym /Cursos /C# SELF /Filtrando elementos

Filtrando elementos

C# SELF
Nível 29, Lição 0
Disponível

1. Jeitos básicos de filtrar coleções

Filtrar é tipo uma peneira de ouro, só que ao invés de pepitas a gente pega só os elementos que precisa da coleção. Por exemplo, temos uma lista de usuários — queremos achar só os maiores de idade, ou só os estudantes, ou só quem curte café (programador, né). Selecionar os elementos certos é uma tarefa super comum, aparece em tudo: desde trabalhar com banco de dados até tratar entrada do usuário.

Bora ver jeitos diferentes de filtrar em C#. Conforme a gente for aprendendo, vamos evoluir nosso app de console de estudo, colocando filtros nele.

Filtragem manual usando loop

Vamos começar pelo jeito mais simples e clássico: filtrar usando foreach:


// Exemplo: tem uma lista de números, precisa pegar só os pares

List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
List<int> evenNumbers = new List<int>();

foreach (int number in numbers)
{
    if (number % 2 == 0) // se o número é par
    {
        evenNumbers.Add(number);
    }
}

Console.WriteLine("Números pares:");
foreach (int n in evenNumbers)
{
    Console.WriteLine(n);
}

Esse jeito sempre funciona, é fácil de entender, mas não é o mais compacto nem o mais "moderno".

Por que filtrar manualmente nem sempre é legal?

Quando você tem outra coleção, outro critério de filtragem, ou precisa escrever vários filtros de uma vez — acaba ficando um monte de código parecido. A gente quer algo mais compacto, legível e modular.

2. Filtrando por critérios mais complexos

Imagina que temos uma coleção de objetos. Vamos pegar o exemplo dos usuários do nosso app de estudo.


public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
    public bool IsStudent { get; set; }
}

Declarando uma lista de usuários:


List<User> users = new List<User>
{
    new User { Name = "Anya", Age = 17, IsStudent = true },
    new User { Name = "Boris", Age = 21, IsStudent = false },
    new User { Name = "Vika", Age = 19, IsStudent = true },
    new User { Name = "Gleb", Age = 25, IsStudent = false }
};

Exemplo 1: Pegar todos os estudantes


List<User> students = new List<User>();
foreach (User user in users)
{
    if (user.IsStudent)
        students.Add(user);
}

Console.WriteLine("Lista de estudantes:");
foreach (User user in students)
{
    Console.WriteLine($"{user.Name} ({user.Age})");
}

Exemplo 2: Pegar estudantes maiores de idade


List<User> adults = new List<User>();
foreach (User user in users)
{
    if (user.Age >= 18 && user.IsStudent)
        adults.Add(user);
}

Console.WriteLine("Estudantes maiores de idade:");
foreach (User user in adults)
{
    Console.WriteLine($"{user.Name} ({user.Age})");
}

E se os critérios de filtragem mudam?

Dá pra colocar as condições de filtragem em métodos separados, pra chamar eles dentro do loop:


bool IsAdult(User u) { return u.Age >= 18; }
bool IsStudent(User u) { return u.IsStudent; }

List<User> filtered = new List<User>();
foreach (User user in users)
{
    if (IsAdult(user) && IsStudent(user))
        filtered.Add(user);
}

3. Filtrando por chave em dicionários

Listas e arrays são de boa, mas a gente também trabalha muito com dicionários.

Imagina que temos um dicionário onde a chave é o nome do usuário e o valor é a idade:


Dictionary<string, int> ageByName = new Dictionary<string, int>
{
    ["Anya"] = 17,
    ["Boris"] = 21,
    ["Vika"] = 19,
    ["Gleb"] = 25
};

Desafio: pegar só usuários 18+


Dictionary<string, int> adults = new Dictionary<string, int>();
foreach (var pair in ageByName)
{
    if (pair.Value >= 18)
        adults.Add(pair.Key, pair.Value);
}

Console.WriteLine("Maiores de idade:");
foreach (var pair in adults)
{
    Console.WriteLine($"{pair.Key}: {pair.Value} anos");
}

Desafio: pegar usuários com nomes que começam com "V"


Dictionary<string, int> namesWithV = new Dictionary<string, int>();
foreach (var pair in ageByName)
{
    if (pair.Key.StartsWith("V"))
        namesWithV.Add(pair.Key, pair.Value);
}

Console.WriteLine("Nomes começando com 'V':");
foreach (var pair in namesWithV)
{
    Console.WriteLine($"{pair.Key}: {pair.Value} anos");
}

4. Princípios da filtragem

Como funciona o processo de filtragem


┌──────────────────────────────────┐
│  Lista: [1, 2, 3, 4, 5, 6]       │
└──────────────────────────────────┘
         │
         ▼
    [Checagem: n % 2 == 0]
         │
         ▼
┌──────────────────────────────────┐
│  Resultado: [2, 4, 6]            │
└──────────────────────────────────┘

Combinando filtros: filtrando por várias condições

Dá pra fazer filtragens em sequência, se quiser selecionar os dados por etapas:


// Primeiro pega só os estudantes
List<User> onlyStudents = new List<User>();
foreach (User user in users)
{
    if (user.IsStudent)
        onlyStudents.Add(user);
}

// Depois, entre eles, pega só os maiores de idade
List<User> adultStudents = new List<User>();
foreach (User user in onlyStudents)
{
    if (user.Age >= 18)
        adultStudents.Add(user);
}

Ou tudo de uma vez:


List<User> adultStudents = new List<User>();
foreach (User user in users)
{
    if (user.IsStudent && user.Age >= 18)
        adultStudents.Add(user);
}

Ordenação e outras operações

Dá pra ordenar usando o método Sort nas listas:


// Estudantes maiores de idade, ordenados por idade
adultStudents.Sort((a, b) => a.Age.CompareTo(b.Age));

Vamos falar mais sobre ordenação na próxima aula!

5. Filtragem em cenários de usuário

1. Filtrando entrada do usuário

Imagina que nosso app recebe uma lista de notas e precisa pegar só as "cinco" (nota máxima).


Console.Write("Digite as notas separadas por espaço: ");
string input = Console.ReadLine();

List<int> grades = new List<int>();
foreach (string s in input.Split(' '))
{
    if (int.TryParse(s, out int grade))
        grades.Add(grade);
}

List<int> fives = new List<int>();
foreach (int grade in grades)
{
    if (grade == 5)
        fives.Add(grade);
}

Console.WriteLine("Notas cinco:");
foreach (var grade in fives)
{
    Console.WriteLine(grade);
}

2. Filtrando por várias condições

Desafio: pegar usuários estudantes com idade de 18 até 22 anos (inclusive).


List<User> filtered = new List<User>();
foreach (User user in users)
{
    if (user.IsStudent && user.Age >= 18 && user.Age <= 22)
        filtered.Add(user);
}

3. Filtrando pela presença de um elemento

Digamos que temos uma lista de strings e queremos pegar só as que contêm a substring ".net" (sem diferenciar maiúsculas/minúsculas).


List<string> technologies = new List<string> { "C#", ".NET", "Java", "dotnet", "JavaScript" };

List<string> netTechs = new List<string>();
foreach (var tech in technologies)
{
    if (tech.ToLower().Contains(".net"))
        netTechs.Add(tech);
}

foreach (var tech in netTechs)
{
    Console.WriteLine(tech);
}

6. Particularidades e erros comuns na filtragem

Filtrar parece fácil, mas dá pra fazer besteira. Bora ver algumas particularidades.

Mudando a coleção original

Se você filtra a coleção original e depois muda ela depois da filtragem, — o resultado não muda, se você já criou uma nova lista. Mas se só guardou a referência pra lista antiga, mudar a coleção original pode afetar o resultado.


List<int> filtered = new List<int>();
foreach (int n in numbers)
{
    if (n > 2)
        filtered.Add(n);
}

// Vamos mudar a lista original
numbers.Add(10);

foreach (var n in filtered)
{
    Console.WriteLine(n); // 10 não vai aparecer aqui
}

Resultado da filtragem manual

O resultado da filtragem manual normalmente é uma nova lista mutável (tipo List<T>), que você pode mexer à vontade — adicionar, remover elementos e tal.

Filtragem e performance

Os filtros nos loops são chamados pra cada elemento da coleção, então se a função dentro da condição for pesada — cuidado. Às vezes é melhor fazer um loop foreach simples, principalmente se tem lógica complicada, precisa logar ou fazer outras coisas junto.

2
Tarefa
C# SELF, nível 29, lição 0
Bloqueado
Filtrando um dicionário por valores
Filtrando um dicionário por valores
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION