LINQ - Usando os operadores padrão de consulta para ir além do básico


 No artigo de hoje vou mostrar como usar funções e operadores padrão de consulta LINQ de forma a simplificar as operações de processamento de dados.

Os operadores de consulta padrão fornecem recursos de consulta, incluindo filtragem, projeção, agregação, classificação e muito mais.

Se você é desenvolvedor .NET com certeza já conhece os recursos e vantagens da LINQ como linguagem de consulta para obter e filtrar dados de várias fontes de dados.Os operadores de consulta padrão são os métodos que formam o padrão da Language-Integrated Query (LINQ).

A maioria destes métodos operam em seqüências, onde uma seqüência é um objeto cujo tipo implementa a interface IEnumerable<T> ou a interface IQueryable<T>.

Tudo bem, mas a LINQ pode fazer mais do que isso se combinarmos várias funções e operadores associados à consulta LINQ para realizar um processamento e consulta a dados mais robusto.

A seguir veremos alguns exemplos usando operadores e funções da LINQ e sendo usados para consultar e processar dados agrupados por categoria.

Agregação|

Uma operação de agregação calcula um valor a partir de uma coleção de valores: Sum, Average, Max. Min, Count, etc.

        public static void Agregacao()
        {
            //Exemplos de agregação
            int[] dados = { 1, 2, 3, 4, 5, 6 , 7, 8 };
            //Soma de números
            Console.WriteLine(dados.Sum());     //resultado => 35
            //Média aritmética de números
            Console.WriteLine(dados.Average()); //Resultado => 4,5
            //Número Máximo
            Console.WriteLine(dados.Max());     //Resultado => 8
            String[] strdados = { "1", "dois", "tres", "quatro", "cinco" };
            //Item com o comprimento minimo
            Console.WriteLine(strdados.Min());  //Ans :1
            //Item com o tamanho minimo
            Console.WriteLine(strdados.Min(f => f.Length));  //Resultado => 1
            //Item com o tamanho maximo
            Console.WriteLine(strdados.Max(f => f.Length));  //Resultado => 6
            Console.ReadLine();
        }
    Private Sub Agregacao()
        'Exemplo de agregação
        Dim dados As Integer() = {1, 2, 3, 4, 5, 6, 7, 8}
        'Soma de números
        Console.WriteLine(dados.Sum())         'resultado => 35
        'Média aritmética de números
        Console.WriteLine(dados.Average())    'Resultado => 4,5
        'Número Máximo
        Console.WriteLine(dados.Max())         'Resultado => 8
        Dim strdados As [String]() = {"1", "dois", "tres", "quatro", "cinco"}
        'Item com o comprimento minimo
        Console.WriteLine(strdados.Min())                                     'Resultado => 1
        'Item com o tamanho minimo
        Console.WriteLine(strdados.Min(Function(f) f.Length))         'Resultado => 1
        'Item com o tamanho maximo
        Console.WriteLine(strdados.Max(Function(f) f.Length))         'Resultado => 6
        Console.ReadLine()
    End Sub
C# VB .NET

Concatenação

A operação de concatenação ocorre quando desejamos combinar mais de um elemento. Neste exemplo usamos a função Concat para combinar dois arrays.

Esta operação é um atalho à abordagem tradicional que utilizar um foreach ou outra instrução para iterar sobre os arrays e realizar o trabalho.

        
       public static void Concatenacao()
        {
            //Primeiro array
            int[] dados = { 1, 2, 3 };
            //Concatenando com outro array
            int[] resultado = dados.Concat(new int[] { 4, 5, 6 }).ToArray(); //resultado 1,2,3,4,5,6
            foreach (var n in resultado)
            {
                Console.Write( n );
            }
        }
   
 Public Sub Concatenacao()
        'Primeiro array
        Dim dados As Integer() = {1, 2, 3}
        'Concatenando com outro array
        Dim resultado As Integer() = dados.Concat(New Integer() {4, 5, 6}).ToArray()  'resultado 1,2,3,4,5,6
        For Each n In resultado
            Console.Write(n + " ")
        Next
    End Sub
C# VB .NET

.Conversão

Para converter um tipo em outro podemos usar a função Cast. Neste exemplo mostramos como converter a partir de IEnumerable para List e Array usando Cast.

        public static void Conversao()
        {
            object[] dados = { "1", "2", "3", "4", "5" };
            //Converter para Ienumerable<string>
            IEnumerable<string> strEnum = dados.Cast<string>();
            Console.WriteLine(strEnum.GetType());
            //Converter para List
            List<string> strList = dados.Cast<string>().ToList();
            Console.WriteLine(strList.GetType());
            //Converter para Array
            string[] strArray = dados.Cast<string>().ToArray();
            Console.WriteLine(strArray.GetType());
        }
Public Shared Sub Conversao()
	Dim dados As Object() = {"1", "2", "3", "4", "5"}
	'Convereter para Ienumerable<string>
	Dim strEnum As IEnumerable(Of String) = dados.Cast(Of String)()
	Console.WriteLine(strEnum.[GetType]())
	'Converter para List
	Dim strList As List(Of String) = dados.Cast(Of String)().ToList()
	Console.WriteLine(strList.[GetType]())
	'Converter para Array
	Dim strArray As String() = dados.Cast(Of String)().ToArray()
	Console.WriteLine(strArray.[GetType]())
End Sub
C# VB .NET Resultado

Operação Elemento

É muito comum em uma aplicação obter o elemento pelo seu índice ou usando uma consulta.

Podemos usar muitas funções com as quais podemos combinar expressões lambdas para realizar a mesma tarefa: ElementAt(), ElementAtOrDefault(), First(), Last(), SingleOrDefault, etc.

 public static void OperacaoElemento()
        {
            int[] dados = { 1, 2, 3, 4, 5 };
            Console.WriteLine(dados.ElementAt(3));                  //4
            Console.WriteLine(dados.ElementAtOrDefault(10));   //0
            Console.WriteLine(dados.First());                          //1
            string[] nome = { "Macoratti", "Mac", "Visual", "Basic" };
            //O nome com 3 letras
            Console.WriteLine(nome.First(m => m.Length == 3));   //Mac
            //Primeiro nome que é maior que 3
            Console.WriteLine(nome.First(m => m.Length > 3));   //Macoratti
            //Ultimo elemento do array
            Console.WriteLine(nome.Last());                              //Basic
            //tenta obter o item cujo tamanho é 6
            Console.WriteLine(nome.SingleOrDefault(m => m.Length == 6));  //Visual
        }
Public Sub OperacaoElemento()
        Dim dados As Integer() = {1, 2, 3, 4, 5}
        Console.WriteLine(dados.ElementAt(3))                  'Erro
        Console.WriteLine(dados.ElementAtOrDefault(10))   '0
        Console.WriteLine(dados.First())                           '1
        Dim nome As String() = {"Macoratti", "Mac", "Visual", "Basic"}
        'O nome com 3 letras
        Console.WriteLine(nome.First(Function(m) m.Length = 3))            'Mac
        'Primeiro nome que é maior que 3
        Console.WriteLine(nome.First(Function(m) m.Length > 3))            'Macoratti
        'Ultimo elemento do array
        Console.WriteLine(nome.Last())                                                 'Basic
        'tenta obter o item cujo tamanho é 6
        Console.WriteLine(nome.SingleOrDefault(Function(m) m.Length = 6))  'Visual
    End Sub
C# VB .NET

Igualdade

A verificação de igualdade entre lista e algum tipo de coleção é outra operação comum em uma aplicação.

Se desejarmos verificar se as palavras estão sequencialmente arranjadas ou não podemos usar a função SequenceEqual que determina se duas seqüências são iguais comparando os elementos usando um comparador de igualdade padrão para o tipo.

  public static void Igualdade()
   {
        //Verificando igualdade
        string[] palavras = { "macoratti", "Visual", "Basic" };
       //Verifica se todos os itens são apresentado em sequencia
       palavras.SequenceEqual(new[] { "macoratti", "Visual", "Basic" });  //True
 
      // Caixa Alta é diferente
       palavras.SequenceEqual(new[] { "MACORATTI", "VISUAL", "BASIC" }); //False

      // Ignorando a caixa alta e baixa na verificação
      palavras.SequenceEqual(new[] { "MACORATTI", "VISUAL", "BASIC"}, StringComparer.OrdinalIgnoreCase);  //True
 }
 Public Sub Igualdade()

        'Verificando igualdade
        Dim palavras As String() = {"macoratti", "Visual", "Basic"}
        Dim teste As String() = {"MACORATTI", "VISUAL", "BASIC"}
        'Verifica se todos os itens são apresentado em sequencia
        palavras.SequenceEqual({"macoratti", "Visual", "Basic"})  'True
        ' Caixa Alta é diferente
        palavras.SequenceEqual(teste)                                    'False
        ' Ignorando a caixa alta e baixa na verificação
        palavras.SequenceEqual(teste, StringComparer.OrdinalIgnoreCase)  'True

 End Sub
C# VB .NET

Particionamento

Esta operação divide o todo em duas partições e obtém uma delas. Neste exemplo veremos algumas funções combinadas com expressões lambdas: Take(), Skip(), TakeWhile(), SkipWhile(), etc.

       public static void Particionamento()
        {
            string[] nome = { "Macoratti", ".Net", "Mac", "Visual", "Basic" };
            // pega dois elementos da lista
            List<string> valor1 = nome.Take(2).ToList<string>();           // Macoratti .Net
            //Pula o primeiro elemento na lista
            List<string> valor2 = nome.Skip(1).ToList<string>();             // .Net, Mac Visual Basic
            // Pega elementos com tamanho igual a 3
            IEnumerable<string> valor3 = nome.TakeWhile(f => f.Length == 3);  //Mac
            // Pula o elemento quando o tamanho for menor que 4
            IEnumerable<string> valor4 = nome.SkipWhile(f => f.Length < 5) ;   // .Net Mac
        }  
 Public Sub Particionamento()
        Dim nome As String() = {"Macoratti", ".Net", "Mac", "Visual", "Basic"}
        ' pega dois elementos da lista
        Dim valor1 As List(Of String) = nome.Take(2).ToList()         ' Macoratti .Net
        'Pula o primeiro elemento na lista
        Dim valor2 As List(Of String) = nome.Skip(1).ToList()         ' .Net, Mac Visual Basic
        ' Pega elementos com tamanho igual a 3
        Dim valor3 As IEnumerable(Of String) = nome.TakeWhile(Function(f) f.Length = 3)         'Mac
        ' Pula o elemento quando o tamanho for menor que 4
        Dim valor4 As IEnumerable(Of String) = nome.SkipWhile(Function(f) f.Length < 5)         ' .Net Mac
    End Sub
C# VB .NET

Projeção

Esta operação é necessária quando desejamos obter certa parte da coleção. No exemplo obtemos parte do array de nomes pelo tamanho e sua posição no índice: Select() , SelectMany(), etc.

        public static void Projecao()
        {
            string[] nome = { "um", "dois", "cinco" };
            //Encontra o tamanho de todos os elementos
            nome.Select(f => f.Length);  // 3 3 4
            //imprimei elemento com indice
            nome.Select((a, b) => b.ToString() + ":" + a);  // 0 : um 1: dois 2:cinco
            //Imprime o item no de vezes pelo seu indice
            nome.SelectMany((a, b) => Enumerable.Repeat(a, b)).ToArray(); //dois 
        }
  Public Sub Projecao()

        Dim nome As String() = {"um", "dois", "cinco"}

        'Encontra o tamanho de todos os elementos
        nome.Select(Function(f) f.Length)         ' 3 3 4
        'imprime elemento com indice
        nome.Select(Function(a, b) b.ToString() + ":" + a)        ' 0 : um 1: dois 2:cinco
        'Imprime o item no de vezes pelo seu indice
        nome.SelectMany(Function(a, b) Enumerable.Repeat(a, b)).ToArray()         'dois 
    End Sub
C# VB .NET

Filtragem

Filtrar é uma operação muito essencial. Neste exemplo veremos algumas funções úteis para filtrar associada com expressão lambda : OrderBy(), OrderByDescending(), etc.

        public static void Filtragem()
        {
            //Ordena
            string[] nome = {"um","dois","cinco" };
            //Ordena a coleção alfabeticamente - primeiro caractere
            nome.OrderBy(f => f).ToArray();     
            // arranja alfabeticamente pelo segundo caractere
            nome.OrderBy(f => f[1]);            
            //Ordena pelo tamanho
            nome.OrderBy(f => f.Length);        
            //Ordena pelo tamanho descendente
            nome.OrderByDescending(f => f.Length);
            // Primeiro pelo tamanho depois Descendente
            nome.OrderBy(f => f.Length).ThenByDescending(f => f); 
        }
Public Sub Filtragem()
        'Ordena
        Dim nome As String() = {"um", "dois", "cinco"}
        'Ordena a coleção alfabeticamente - primeiro caractere
        nome.OrderBy(Function(f) f).ToArray()
        ' arranja alfabeticamente pelo segundo caractere
        nome.OrderBy(Function(f) f(1))
        'Ordena pelo tamanho
        nome.OrderBy(Function(f) f.Length)
        'Ordena pelo tamanho descendente
        nome.OrderByDescending(Function(f) f.Length)
        ' Primeiro pelo tamanho depois Descendente
        nome.OrderBy(Function(f) f.Length).ThenByDescending(Function(f) f)
    End Sub  
C# VB .NET

Com esses exemplos você pode ter uma ideia do como usar os operadores padrão da LINQ combinado com algumas funções para turbinar o seu código.

Pegue o projeto completo aqui : Operadores_LINQ.zip

Disse-lhes, pois, Jesus: Quando levantardes o Filho do homem, então conhecereis que EU SOU, e que nada faço por mim mesmo; mas isto falo como meu Pai me ensinou.
João 8:28

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti