Algoritmo agregado de LINQ explicado

Resuelto Alexander Beletsky asked hace 13 años • 12 respuestas

Esto puede parecer poco convincente, pero no he podido encontrar una explicación realmente buena Aggregate.

Bueno significa breve, descriptivo, completo con un ejemplo pequeño y claro.

Alexander Beletsky avatar Aug 18 '11 16:08 Alexander Beletsky
Aceptado

La definición más fácil de entender Aggregatees que realiza una operación en cada elemento de la lista teniendo en cuenta las operaciones anteriores. Es decir, realiza la acción sobre el primer y segundo elemento y traslada el resultado. Luego opera sobre el resultado anterior y el tercer elemento y continúa. etc.

Ejemplo 1. Sumar números

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

Esto suma 1y 2para hacer 3. Luego agrega 3(resultado del anterior) y 3(siguiente elemento en secuencia) para crear 6. Luego agrega 6y 4para hacer 10.

Ejemplo 2. crear un csv a partir de una matriz de cadenas

var chars = new []{"a","b","c","d"};
var csv = chars.Aggregate( (a,b) => a + ',' + b);
Console.WriteLine(csv); // Output a,b,c,d

Esto funciona de manera muy similar. Concatenar auna coma y bhacer a,b. Luego concatena a,b con una coma y cpara hacer a,b,c. etcétera.

Ejemplo 3. Multiplicar números usando una semilla

Para completar, hay una sobrecarga que Aggregatetoma un valor inicial.

var multipliers = new []{10,20,30,40};
var multiplied = multipliers.Aggregate(5, (a,b) => a * b);
Console.WriteLine(multiplied); //Output 1200000 ((((5*10)*20)*30)*40)

Al igual que los ejemplos anteriores, esto comienza con un valor de 5y lo multiplica por el primer elemento de la secuencia 10dando un resultado de 50. Este resultado se traslada y se multiplica por el siguiente número de la secuencia 20para dar un resultado de 1000. Esto continúa a través de los 2 elementos restantes de la secuencia.

Ejemplos en vivo: http://rextester.com/ZXZ64749
Docs: http://msdn.microsoft.com/en-us/library/bb548651.aspx


Apéndice

El ejemplo 2 anterior utiliza la concatenación de cadenas para crear una lista de valores separados por una coma. Esta es una forma simplista de explicar el uso que Aggregatefue la intención de esta respuesta. Sin embargo, si se utiliza esta técnica para crear una gran cantidad de datos separados por comas, sería más apropiado utilizar un archivo StringBuilder, y esto es totalmente compatible con Aggregateel uso de la sobrecarga inicializada para iniciar el archivo StringBuilder.

var chars = new []{"a","b","c", "d"};
var csv = chars.Aggregate(new StringBuilder(), (a,b) => {
    if(a.Length>0)
        a.Append(",");
    a.Append(b);
    return a;
});
Console.WriteLine(csv);

Ejemplo actualizado: http://rextester.com/YZCVXV6464

Jamiec avatar Aug 18 '2011 09:08 Jamiec

Depende en parte de qué sobrecarga estás hablando, pero la idea básica es:

  • Comience con una semilla como "valor actual"
  • Iterar sobre la secuencia. Para cada valor de la secuencia:
    • Aplicar una función especificada por el usuario para transformarse (currentValue, sequenceValue)en(nextValue)
    • ColocarcurrentValue = nextValue
  • devolver la finalcurrentValue

Puede que la Aggregatepublicación de mi serie Edulinq le resulte útil: incluye una descripción más detallada (incluidas las diversas sobrecargas) e implementaciones.

Un ejemplo sencillo es utilizar Aggregatecomo alternativa a Count:

// 0 is the seed, and for each item, we effectively increment the current value.
// In this case we can ignore "item" itself.
int count = sequence.Aggregate(0, (current, item) => current + 1);

O tal vez sumar todas las longitudes de las cadenas en una secuencia de cadenas:

int total = sequence.Aggregate(0, (current, item) => current + item.Length);

Personalmente, rara vez lo encuentro Aggregateútil: los métodos de agregación "adaptados" suelen ser lo suficientemente buenos para mí.

Jon Skeet avatar Aug 18 '2011 09:08 Jon Skeet

Una imagen vale mas que mil palabras

Recordatorio:
Func<X, Y, R>es una función con dos entradas de tipo Xy Y, que devuelve un resultado de tipo R.

Enumerable.Aggregate tiene tres sobrecargas:

Sobrecarga 1:

A Aggregate<A>(this IEnumerable<A> a, Func<A, A, A> f)

Agregado1

Ejemplo:

new[]{1,2,3,4}.Aggregate((x, y) => x + y);  // 10

Esta sobrecarga es simple, pero tiene las siguientes limitaciones:

  • la secuencia debe contener al menos un elemento;
    de lo contrario, la función arrojará un archivo InvalidOperationException.
  • Los elementos y el resultado deben ser del mismo tipo.


Sobrecarga 2:

B Aggregate<A, B>(this IEnumerable<A> a, B bIn, Func<B, A, B> f)

Agregado2

Ejemplo:

var hayStack = new[] {"straw", "needle", "straw", "straw", "needle"};
var nNeedles = hayStack.Aggregate(0, (n, e) => e == "needle" ? n+1 : n);  // 2

Esta sobrecarga es más general:

  • se debe proporcionar un valor inicial ( bIn).
  • la colección puede estar vacía;
    en este caso, la función arrojará el valor inicial como resultado.
  • Los elementos y el resultado pueden tener diferentes tipos.


Sobrecarga 3:

C Aggregate<A,B,C>(this IEnumerable<A> a, B bIn, Func<B,A,B> f, Func<B,C> f2)

La tercera sobrecarga no es muy útil en mi opinión.
Lo mismo se puede escribir de manera más sucinta usando la sobrecarga 2 seguida de una función que transforma su resultado.


Las ilustraciones están adaptadas de esta excelente publicación de blog .

3dGrabber avatar Apr 13 '2017 12:04 3dGrabber

Agregar se utiliza básicamente para agrupar o resumir datos.

Según MSDN, "La función agregada aplica una función acumuladora sobre una secuencia".

Ejemplo 1: sumar todos los números de una matriz.

int[] numbers = new int[] { 1,2,3,4,5 };
int aggregatedValue = numbers.Aggregate((total, nextValue) => total + nextValue);

*importante: El valor agregado inicial de forma predeterminada es el primer elemento en la secuencia de recopilación. es decir: el valor inicial de la variable total será 1 de forma predeterminada.

explicación variable

total: contendrá el valor resumido (valor agregado) devuelto por la función.

nextValue: es el siguiente valor en la secuencia de la matriz. Este valor se suma al valor agregado, es decir, al total.

Ejemplo 2: agregar todos los elementos de una matriz. También establezca el valor inicial del acumulador para comenzar a sumar desde 10.

int[] numbers = new int[] { 1,2,3,4,5 };
int aggregatedValue = numbers.Aggregate(10, (total, nextValue) => total + nextValue);

explicación de los argumentos:

el primer argumento es el inicial (valor inicial, es decir, valor inicial) que se utilizará para comenzar la suma con el siguiente valor de la matriz.

el segundo argumento es una función que toma 2 int.

1.total: esto se mantendrá igual que antes del valor de suma (valor agregado) devuelto por la función después del cálculo.

2.nextValue:: es el siguiente valor en la secuencia de la matriz. Este valor se suma al valor agregado, es decir, al total.

Además, depurar este código le permitirá comprender mejor cómo funcionan los agregados.

maxspan avatar Sep 19 '2014 01:09 maxspan