Hoje vou apresentar os novos métodos DistinctBy e ExceptBy da LINQ que operam com conjuntos e estão disponíveis a partir do .NET 6. |
As operações de conjunto na LINQ
referem-se a operações de consulta que geram um conjunto de resultados baseado
na presença ou ausência de elementos equivalentes dentro da mesma coleção ou de
coleções ou conjuntos separados.
Os métodos usados até o momento para realizar estas operações são :
Esses métodos realizam operações em conjuntos em comparação com outros conjuntos de valores.
A partir do NET 6 foram incluídos os seguintes métodos para operações de conjunto :
Eles possuem o mesmo objetivo dos
métodos anteriores com a diferença de que operam em objetos complexos e que
eles utilizam uma chave de seleção(KeySelector) usada como um discriminador comparativo
para realizar as respectivas operações.
Assim, esses novos métodos utilizam uma propriedade/objeto que deve fazer parte das
coleções envolvidas, dispensando assim implementações baseadas na interface
IEqualityComparer que eram requeridas por extensões
LINQ mais antigas como Union e Intersect.
Neste artigo iremos apresentar um exemplo dos dois primeiros métodos para ilustrar o seu funcionamento.
Usando o método DistinctBy
Vamos criar um projeto Console (.NET Core) no NET 6 chamado LINQ_DistinctBy.
No projeto criado vamos abrir a classe Program e definir um tipo record Aluno:
public record Aluno |
A seguir vamos criar uma lista de alunos :
var alunos = new[] { new Aluno() {Nome = "Maria", Idade = 40}, new Aluno() {Nome = "Jaime", Idade = 40}, new Aluno() {Nome = "Jose", Idade = 35}, new Aluno() {Nome = "Evelyn", Idade = 30}, new Aluno() {Nome = "Rodrigo", Idade = 36}, new Aluno() {Nome = "Sonia", Idade = 35}, new Aluno() {Nome = "Paulo", Idade = 36}, new Aluno() {Nome = "Carlos", Idade = 33} }; |
Para mostrar a atuação do método DistinctBy vamos obter uma lista de alunos com idades únicas ou distintas. Para isso vamos definir a seguinte consulta LINQ
var alunosComIdadesDistintas = alunos.DistinctBy(x => x.Idade);
Aqui usamos o método DistinctBy e definimos a propriedade Idade como a chave de seleção usada como critério para obter a lista de alunos com idades únicas.
Podemos inclusive realizar a ordenação do resultado :
var alunosComIdadesDistintas = alunos.DistinctBy(x => x.Idade).OrderBy(x=> x.Nome);
A seguir podemos percorrer o resultado obtido, que é um IEnumerable<T>, e exibir os nomes dos alunos:
foreach(var aluno in alunosComIdadesDistintas)
Console.WriteLine($"Aluno {aluno.Nome} tem
{aluno.Idade} anos");
O código completo do projeto é dado a seguir:
var alunos = new[] { new Aluno() {Nome = "Maria", Idade = 40}, new Aluno() {Nome = "Jaime", Idade = 40}, new Aluno() {Nome = "Jose", Idade = 35}, new Aluno() {Nome = "Evelyn", Idade = 30}, new Aluno() {Nome = "Rodrigo", Idade = 36}, new Aluno() {Nome = "Sonia", Idade = 35}, new Aluno() {Nome = "Paulo", Idade = 36}, new Aluno() {Nome = "Carlos", Idade = 33} }; Console.WriteLine("\n### Usando DistinctBy ###\n"); var alunosComIdadesDistintas = alunos.DistinctBy(x => x.Idade).OrderBy(y=> y.Idade); foreach(var aluno in alunosComIdadesDistintas) Console.ReadKey(); public record Aluno |
Obs: Aqui usamos o recurso das instruções de nível superior
Executando o projeto teremos o resultado a abaixo:
Usando o método ExceptBy
Vamos criar outro projeto Console (.NET Core) no NET 6 chamado LINQ_ExceptBy.
No projeto criado vamos abrir a classe Program e definir um tipo record Planeta:
public record Planeta { public string? Nome { get; init; } public string? Tipo { get; init; } } |
A seguir vamos criar uma lista de planetas contendo todos os planetas do sistema solar:
var planetas = new [] { new Planeta{Nome="Mercurio",Tipo = "Rochoso"}, new Planeta{Nome="Vênus", Tipo="Rochoso"}, new Planeta{Nome="Marte", Tipo="Rochoso"}, new Planeta{Nome="Terra", Tipo="Rochoso"}, new Planeta{Nome="Júpiter", Tipo="Gasoso"}, new Planeta{Nome="Saturno", Tipo="Gasoso"}, new Planeta{Nome="Urano", Tipo="Gasoso"}, new Planeta{Nome="Netuno", Tipo="Gasoso"}, new Planeta{Nome="Plutão", Tipo="Rochoso"} }; |
Vamos criar também outra lista de planetas gasosos (jovianos) :
var jovianos = new[] { new Planeta{Nome="Júpiter", Tipo="Gasoso"}, new Planeta{Nome="Saturno", Tipo="Gasoso"}, new Planeta{Nome="Urano", Tipo="Gasoso"}, new Planeta{Nome="Netuno", Tipo="Gasoso"} }; |
Feito isso, o nosso objetivo será obter
uma lista dos planetas com exceção dos planetas jovianos. Para isso usamos o
método Exceptby onde :
1 - Vamos definir a coleção que contem os elementos que desejamos retirar da
primeira coleção , ou seja da coleção planetas, e, aplicar o método
ExceptBy;
2
- A seguir vamos definir a chave de seleção que é a propriedade
Nome;
var
planetasExcetoJovianos = planetas.ExceptBy(jovianos.Select(p => p.Nome), p =>
p.Nome).OrderBy(x=> x.Nome);
Com isso vamos obter todos os planetas, exceto aqueles planetas cujo nome
identificam um planeta joviano ou gasoso,
e, ainda estamos ordenando o resultado.
O código completo do projeto é dado a seguir:
var planetas = new [] { new Planeta{Nome="Mercurio",Tipo = "Rochoso"}, new Planeta{Nome="Vênus", Tipo="Rochoso"}, new Planeta{Nome="Marte", Tipo="Rochoso"}, new Planeta{Nome="Terra", Tipo="Rochoso"}, new Planeta{Nome="Júpiter", Tipo="Gasoso"}, new Planeta{Nome="Saturno", Tipo="Gasoso"}, new Planeta{Nome="Urano", Tipo="Gasoso"}, new Planeta{Nome="Netuno", Tipo="Gasoso"}, new Planeta{Nome="Plutão", Tipo="Rochoso"} }; var jovianos = new[] Console.WriteLine("\n### Usando ExceptBy ###\n"); foreach(var planeta in planetasExcetoJovianos) Console.ReadKey(); public record Planeta |
Obs: Aqui usamos o recurso das instruções de nível superior
Executando o projeto teremos o seguinte resultado:
Com o uso destes métodos temos um código mais sucinto e legível e que realiza a tarefa proposta em apenas uma etapa.
Na próxima parte do artigo veremos os métodos : IntercepBy e UnionBy
Pegue o código dos dois projetos aqui : linq1.zip
"Deus
"retribuirá a cada um conforme o seu procedimento".
Ele dará vida eterna aos que, persistindo em fazer o bem, buscam glória,
honra e imortalidade."
Romanos 2:6,7
E estamos conversados.
Referências:
C# - Lendo e escrevendo em arquivos textos e binários
C# - Entendo o I/O na plataforma .NET
C# - Fluxo assíncrono ou async streams
C#- Apresentando Streams assíncronos
.NET 6 - LINQ - Usando o método Chunk