C# -  Evitando loops aninhados com LINQ


 Neste artigo veremos como analisar, ou seja, fazer o parse de um arquivo CSV.

Escrever código pode ser muito interessante, mas também pode ser muito frustrante se o seu código for baseado em loops aninhados visto que as iterações ainda são uma das partes mais importantes na codificação.

Então, como podemos evitar o uso de loops aninhados em nosso código ?

Evitar loops aninhados pode ajudar a tornar o seu código mais limpo, legível e eficiente e dentre as opções para fazer isso vamos focar na utilização da LINQ.

A LINQ ou Language Integrated Query fornece uma maneira de expressar consultas diretamente na linguagem C# adicionando expressões de consulta, que são semelhantes às consultas SQL.

A sintaxe LINQ é geralmente menos eficiente que um loop foreach. Sim, isso mesmo. Não usamos a LINQ para ter eficiência mas para melhorar a legibilidade do código.

Assim na maioria das vezes, a LINQ será um pouco mais lento porque apresenta uma sobrecarga.  Então não use a LINQ se você se precisa ter desempenho, use-a para ter um código mais enxuto e mais legível e assim facilitar a manutenção.

Quais são então os benefícios da LINQ ?

Seguem alguns...

- Você pode acessar novas tecnologias sem saber muito sobre elas;
- A LINQ oferece uma maneira baseada em objeto e integrada à linguagem de consultar dados, não importa de onde esses dados venham. Assim, através do LINQ podemos consultar banco de dados, XML e coleções.
crie aplicativos completos com menos código
- Permite desenvolver aplicações em menos tempo e com menos erros;
- Permite combinar fontes de dados sem recorrer a truques de programação estranhos;
- Faz com que novos desenvolvedores trabalhem mais rápido;
- Permite verificar a sintaxe em tempo de compilação;
- Permite consultar coleções como arrays, classes enumeráveis, etc., na linguagem nativa do seu aplicativo, como VB ou C#, da mesma forma que você consultaria um banco de dados usando SQL

A seguir temos a anatomia geral de uma consulta usando a LINQ:

variavel = IEnumerable.MetodoLINQ(v=> v.FazAlgumaCoisa());

- variavel : armazena o resultado
- IEnumerable
: List/Array ou outro IEnumerable
- MetodoLINQ
: Where/Select/SelectMany,Aggregate,Sum,Count, etc.
- v
: parâmetro de entrada
- FazAlgumaCoisa
: Método que vai operar em cada elemento da coleção;

Os loops e a LINQ

Vejamos a seguir como substituir loops usando consultas LINQ.

1- Iterar em uma coleção e obter o resultado da multiplação dos itens

int[] numeros = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

int c = 1;

for
(int i = 0; i < numeros.Length; ++i)
{
   c *= numeros[i];
}

Console.WriteLine(
"Resultado da multiplicação " + c);

Usando a LINQ : Método Aggregate com semente

int[] numeros = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

int resultado = numeros.Aggregate(1, (n1, n2) => n1 * n2);

Console.WriteLine(resultado);
 

2- Preencher um array onde cada elemento é a soma com o seu anterior e exibir  o seu contéudo :

var vetor = new int[100];

for (var n = 0; n < vetor.Length; n++)
    vetor[n] = n + n;

foreach (int x in vetor)
    Console.Write(
$"{x} ");
 

Usando a LINQ na sintaxe de consulta com Enumerable.Range :

var vetor = (from n in Enumerable.Range(0, 100)
    
select n + n).ToArray();

foreach (int x in vetor)
    Console.Write(
$"{x} ");
 

3-  Loop aninhado com 3 níveis mais difícil de ler e entender:

for (int i = 0; i < 10; i++)
{
  
for (int j = 0; j < 10; j++)
   {
      
for (int k = 0; k < 10; k++)
       { 
           Console.Write(
$"{k} {j} {i}");
       }
    }
}

Usando a LINQ com Enumerable.Range :

var numeros = from I in Enumerable.Range(0, 10)
             
from J in Enumerable.Range(0, 10)
             
from K in Enumerable.Range(0, 10)
             
select new { I, J, K };

foreach (var n in numeros)
{
  Console.WriteLine(n);
}

O método Enumerable.Range gera uma sequência de números dentro de um intervalo especificado. Para isso ele usa o método estático Range() da classe Enumerable que esta no namespace System.Linq.

4- Filtrar um array de números inteiros aleatórios que possuem o número 3 :

int[] numerosAleatorios = { 127, 264, 33657, 43, 535, 6, 83652, 73, 652, 3043, 236, 896 };

List<int> lista = new();

foreach (int numero in numerosAleatorios)

  
if (numero.ToString().Contains("3"))
   {
     lista.Add(numero);
   }
}

foreach(var n in lista)
  Console.Write(n +
" ");

Usando a LINQ : consulta com cláusula Where

int[] numerosAleatorios = { 127, 264, 33657, 43, 535, 6, 83652, 73, 652, 3043, 236, 896 };

var lista = numerosAleatorios.Where(n => n.ToString().Contains("3"));

foreach (var n in lista)
    Console.Write(n +
" ");

Dessa forma, muitas vezes, e, dependendo dos requisitos, as vantagens do LINQ superam as desvantagens.

A perda de velocidade versus uma legibilidade limpa, escrita mais rápida e aplicação de linguagem baseada em SQL sugere que o uso de expressões LINQ oferece benefícios poderosos para o desenvolvedor.

No entanto você deve estar atento para saber decidir quando vale a pena usar as consultas LINQ.

E estamos conversados...

"Bendito seja o Deus e Pai de nosso Senhor Jesus Cristo que, segundo a sua grande misericórdia, nos gerou de novo para uma viva esperança, pela ressurreição de Jesus Cristo dentre os mortos"
1 Pedro 1:3

Referências:


José Carlos Macoratti