1. demand
What is an accumulator? How to use the accumulator? Don't worry, a new technology is basically born to meet certain needs. Starting from the needs, it is easier to understand the characteristics of this function.
For ease of understanding, suppose there is a one-dimensional array of int, storing 5 numbers, find the sum (-1) of the first value (-1) plus the second value (0), add the calculated value (-1) to the third number (3) of the array, add (2) again, and add the value to the fourth number (5) of the array again... By analogy, the result is: int result = -1 + 0 + 3 + 5 + 8;
int[] numbers={-1, 0, 3, 5,8};
1.1 basic needs
//V1.0版本
static void Main(string[] args)
{
int[] numbers = { -1, 0, 3, 5, 8 };
int result = numbers[0];
for (int i = 1; i < numbers.Length; i++)
{
result = result + numbers[i];
}
Console.WriteLine(result);//输出15
Console.ReadKey();
}
1.2 Encapsulation algorithm part
Extract the algorithm in the middle so that you can enter other int arrays of different lengths:
//V1.1 版本
static void Main(string[] args)
{
int[] numbers = { -1, 0, 3, 5, 8 };
var result = Aggregate(numbers);
Console.WriteLine(result);
Console.ReadKey();
}
static int Aggregate(int[] array)
{
int result = array[0];
for (int i = 1; i < array.Length; i++)
{
result = result + array[i];
}
return result;
}
1.3 Not just implementing addition-algorithmic substitution
The accumulator needs to be more than just adding, for example:
int result = -1 * 0 * 3 * 5 * 8;
int result = -1 - 0 - 3 - 5 - 8;
//V1.2 版本,实现算法替换
//需了解委托,Lambda相关知识
static void Main(string[] args)
{
int[] numbers = { -1, 0, 3, 5, 8 };
var result = Aggregate(numbers,(result,next)=>result * next);//实现乘法
//var result = Aggregate(numbers,(result,next)=>result - next);//实现减法
Console.WriteLine(result);
Console.ReadKey();
}
static int Aggregate(int[] array,Func<int,int,int> func)
{
int result = array[0];
for (int i = 1; i < array.Length; i++)
{
result = func(result, array[i]);
}
return result;
}
1.4 Not just int types-generics
目前该算法int Aggregate(int[] array,Func<int,int,int> func)只支持 int 类型,现在要扩展到任意类型–泛型。
//V1.3 版本,实现泛型
//需了解泛型,IEnumerator接口相关知识
static void Main(string[] args)
{
int[] numbers = { -1, 0, 3, 5, 8 };
var result = Aggregate(numbers, (result, next) => result + next);
Console.WriteLine(result);
Console.ReadKey();
}
static TSource Aggregate<TSource>(IEnumerable<TSource> source,Func<TSource, TSource, TSource> func)
{
using (IEnumerator<TSource> e = source.GetEnumerator())
{
if (!e.MoveNext())
{
throw new ArgumentException();
}
TSource result = e.Current;
while (e.MoveNext())
{
result = func(result, e.Current);
}
return result;
}
}
1.5 Implementation method becomes expansion method
Add extension methods directly to classes that implement the IEnumerator interface. At this point, the functions implemented by this Aggregate are similar to the accumulator provided by the official website.
//V1.4 版本,扩展方法
class Program
{
static void Main(string[] args)
{
int[] numbers = { -1, 0, 3, 5, 8 };
var result = numbers.Aggregate((result, next) => result + next);
Console.WriteLine(result);
Console.ReadKey();
}
}
public static class Helper
{
public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func)
{
using (IEnumerator<TSource> e = source.GetEnumerator())
{
if (!e.MoveNext())
{
throw new ArgumentException("需要至少两个元素");
}
TSource result = e.Current;
while (e.MoveNext())
{
result = func(result, e.Current);
}
return result;
}
}
}
2. APIs provided by Microsoft
Under the System.Linq namespace, you provide:
1. public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func);
2. public static TAccumulate Aggregate<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func);
3. public static TResult Aggregate<TSource, TAccumulate, TResult>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector);
The first interface has the same function as my example above. The other two functions will be explained later (if you have time).
3. from shallow to deep
如果是初学者,可能大脑第一反应还是觉得这个Aggregate只能加减乘除,如果这样想,说明其实还是理解得不够深刻,现在来深度剖析该方法的传参:func。
As shown in the figure below, the accumulator traverses each element. Except for the first time, it directly takes the first and second elements to perform func operation. Starting from the third one, it takes the result of the previous calculation as the first input parameter of func. The second input parameter is the next element of the array until the end of the traversal, and returns a final result value.
Practical use: When a table in the database references foreign keys of multiple tables, when you need to query these foreign keys, you can use an accumulator to accumulate the conditions that need to be queried and query the database.
