C# - Usando o método Aggregate (LINQ)


 Hoje faremos uma abordagem prática ao método Enumerable.Aggregate da LINQ que esta presente no namespace System.Linq.

O método Enumerable.Aggregate é um método de extensão, e, é uma versão C# para as funções fold ou reduce.

Este método atua basicamente aplicando uma função a cada item de uma coleção.

Por exemplo,  para a coleção { 3, 7, 5 } e para a função Add(operator+) teremos como resultado ((3+7)+5)) e retornando o valor 15.

Assim o método Aggregate pode ser usado para agrupar os valores das várias linhas como entrada e retornar a saída como valor único de maior significado, ou seja, uma função agregada retornando um único valor.

Este recurso pode ser usado para avaliar código em tempo de execução e pode ser usado em uma variedade de cenários como por exemplo em um tomador de decisão onde você define um conjunto de regras e em cada regra pode avaliar os parâmetros de entrada e com base nisso, fornecer uma saída.

Como exemplo de aplicação podemos usar o método Aggregate para executar operações matemáticas como Average, Aggregate, Count, Max, Min e Sum na propriedade numérica dos elementos da coleção.

Vejamos dois exemplo básicos:

1- Uma alternativa Aggregate para Sum

Faremos a seguir uma implementação de Sum usando o método Aggregate.

O exemplo a seguir usa a sobrecarga do método Aggregate com apenas um parâmetro func, e, no parâmetro func, passa a expressão lambda (método anônimo) que adiciona dois números.

       static int SumAggregate(List<int> numeros)
        {
            int resultado = numeros.Aggregate(func: (result, item) => result + item);
            return resultado;
        }

Um exemplo de utilização com resultado obtido pode ser visto a seguir:

        static void Main(string[] args)
        {
            var numeros = new List<int> { 4, 6, 2, 8, 3 , 7, 9 , 11, 5};
            var resultado = SumAggregate(numeros);
            Console.WriteLine($"A soma agregada obtida é igual a : {resultado}");
            Console.ReadLine();
        }
        static int SumAggregate(List<int> numeros)
        {
            int resultado = numeros.Aggregate(func: (result, item) => result + item);
            return resultado;
        }

Resultado:

2- Uma alternativa Aggregate para Average

Nesta implementação de Average usamos a sobrecarga do método Aggregate com três parâmetros:  seed, func e resultSelector.

Obs: Este exemplo é apenas uma demonstração. Para calcular o valor médio, é mais simples usar Enumerable.Average.

        static decimal AverageAggregate(List<int> numeros)
        {
            decimal media = numeros.Aggregate(
                    seed: 0,
                    func: (result, item) => result + item,
                    resultSelector: result => (decimal)result / numeros.Count);
            return media;
        }

Um exemplo de utilização com resultado obtido pode ser visto a seguir:

       static void Main(string[] args)
        {
            var numeros = new List<int> { 4, 6, 2, 8, 3 , 7, 9 , 11, 5};
            var resultado = AverageAggregate(numeros);
            Console.WriteLine($"A média agregada obtida é igual a : {resultado}");
            Console.ReadLine();
        }
        static decimal AverageAggregate(List<int> numeros)
        {
            decimal media = numeros.Aggregate(
                    seed: 0,
                    func: (result, item) => result + item,
                    resultSelector: result => (decimal)result / numeros.Count);
            return media;
        }

O resultado da execução acima é o seguinte:

Agora veremos um exemplo onde vamos usar o método Aggregate para implementar a funcionalidade de separar uma string por vírgula.

Por padrão, se quisermos exibir um array em uma única linha, significa que usaremos split, foreach e usaremos o concat, mas neste exemplo vamos usar a função agregada para acumular e resolver isso de forma mais simples:

       static string SepararPorVirgulaAggregate(string[] linguagens)
        {
            var resultado = linguagens.Aggregate((s1, s2) => s1 + ", " + s2);
            return resultado;
        }

Um exemplo de utilização com resultado obtido pode ser visto a seguir:

        static void Main(string[] args)
        {
            string[] linguagens = {
                "C#","JavaScript","Java","VB.NET","C++",
                "Pascal","Pearl","Python","Dart","TypeScript","Go"
            };
            var resultado = SepararPorVirgulaAggregate(linguagens);
            Console.WriteLine(resultado);
            Console.ReadLine();
        }
       static string SepararPorVirgulaAggregate(string[] linguagens)
        {
            var resultado = linguagens.Aggregate((s1, s2) => s1 + ", " + s2);
            return resultado;
        }

O resultado obtido é visto abaixo:

Pegue o projeto aqui:  CShp_Aggregate.zip

"Porque não nos pregamos a nós mesmos, mas a Cristo Jesus, o Senhor; e nós mesmos somos vossos servos por amor de Jesus.
Porque Deus, que disse que das trevas resplandecesse a luz, é quem resplandeceu em nossos corações, para iluminação do conhecimento da glória de Deus, na face de Jesus Cristo."
2 Coríntios 4:5,6

Referências:


José Carlos Macoratti