How does Linq's Aggregate () extension method work?

10

I recently saw some examples that used the Aggregate() of namespace System.Linq method, but I could not find any good explanation of how to use it.

What does this method do and how should it be used?

    
asked by anonymous 06.10.2015 / 15:22

1 answer

8
  

I already answered this here , but not specifically about Aggregate , so I'll isolate the part of the answer that matters.

     

The explanation then goes into the concept of using the Entity Framework, but you can use it for anything that uses Linq.

Aggregate has no equivalent at all and any database system. It's important to explain the concept of it before.

Assume a relation from 1 to N, or from N to N. In our example, suppose that the user now has permissions per screen (I am going to invent a Model named UsuarioPermissao , which is an associative table between Usuario and Permissao ), which is declared in Model Usuario as follows:

public virtual ICollection<UsuarioPermissao> UsuarioPermissoes { get; set; }

For example, making sense, I'll combine Aggregate with another operator, called SelectMany ". SelectMany is analogous to Select , but serves for a set of objects.

Suppose you'd like to return all permissions for all users, and their permissions on a single line, separated by a comma (or by a semicolon, whatever). The Aggregate method does this like this:

var resultado = db.Usuario.SelectMany(p => p.UsuarioPermissoes).
                          .Aggregate("",     // String inicial, chamada de 'acumulador'
                                     // A construção abaixo considera 'str' como a String acumulada e 'usuarioPermissao' como o registro atual da iteração
                                     (str, usuarioPermissao) => str + ", " + usuarioPermissao.Permissao.Nome).ToList();
  

Now I'll translate the examples here , which do not involve databases.

Example 1: Adding numbers

var numeros = new[]{1,2,3,4};
var soma = numeros.Aggregate( (a,b) => a + b);
Console.WriteLine(soma); // resultado: 10 (1+2+3+4)

In this case, Aggregate will accumulate the results of each sum in a , while b is the next number in the sequence.

  • Iteration 1:% with%. a == 1 ( a + 2 ). b == 2 gets 3;
  • Iteration 2:% with%. a ( a == 3 ). a + 3 gets 6;
  • Iteration 3:% with%. b == 3 ( a ). a == 6 gets 10.

Example 2: Concatenating strings separated by commas

var strings = new []{"a","b","c", "d"};
var stringFinal = strings.Aggregate( (a,b) => a + ',' + b);
Console.WriteLine(stringFinal); // resultado: a,b,c,d
  • Iteration 1:% with%. a + 4 ( b == 4 ). a gets "a, b";
  • Iteration 2:% with%. a == "a" ( a + ",b" ). b == "b" gets "a, b, c";
  • Iteration 3:% with%. a ( a == "a,b" ). a + ",c" gets "a, b, c, d";

Example 3: Multiplying numbers using a seed

For full understanding, there is a overload of b == "c" that accepts a seed parameter.

var numeros = new []{10,20,30,40};
var valorMultiplicado = numeros.Aggregate(5, (a,b) => a * b); // A semente é 5
Console.WriteLine(valorMultiplicado); //Resultado: 1200000 ((((5*10)*20)*30)*40)

Example 4: Defining a delegate

Suppose you are reimplementing example 2 and want to implement a more robust logic. There is a form of a that can be used declaring a delegate as follows:

var strings = new []{"a","b","c", "d"};
var stringFinal = strings.Aggregate(new StringBuilder(), (a,b) => {
    if (a.Length > 0)
        a.Append(",");
    a.Append(b);
    return a;
});
Console.WriteLine(stringFinal);
    
06.10.2015 / 15:53