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?
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?
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.
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.
a == 1
( a + 2
). b == 2
gets 3; a
( a == 3
). a + 3
gets 6; b == 3
( a
). a == 6
gets 10. var strings = new []{"a","b","c", "d"};
var stringFinal = strings.Aggregate( (a,b) => a + ',' + b);
Console.WriteLine(stringFinal); // resultado: a,b,c,d
a + 4
( b == 4
). a
gets "a, b"; a == "a"
( a + ",b"
). b == "b"
gets "a, b, c"; a
( a == "a,b"
). a + ",c"
gets "a, b, c, d"; 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)
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);