متدهای بهم پیوسته (Aggregate Methods) در LINQ

LINQ دارای عملگرها یا متدهای به هم پیوسته‌ای است که به شما اجازه می‌دهند که عملیات ریاضی را بر روی مقادیر موجود در یک مجموعه انجام دهید. در ادامه در مورد برخی از این متدها توضیح می‌دهیم.

متدهای Count و LongCount

با استفاده از متدهای Count و LongCount می‌توان تعداد عناصر یک کلکسیون یا آرایه را به دست آورد. از متد Count برای به دست آوردن تعداد عناصر یک کلکسیون و از متد LongCount برای به دست آوردن تعداد عناصر یک کلکسیون بزرگ استفاده می‌شود. به عنوان مثال نحوه استفاده از عملگر Count در زیر آمده است :

int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 };

Console.WriteLine("numbers has {0} elements.", numbers.Count());

یک از سربارگذاری های دو متد فوق به شما اجازه تعیین شمارش عناصری خاص را می‌دهد :

Console.Write("Number of even numbers in the collection: {0}", 
              numbers.Count(n => n % 2 == 0));

عبارت لامبدا در سربارگذاری متد Count در مثال بالا تعیین کننده شرایط عنصری است که ما می‌خواهیم مورد شمارش قرار بگیرد که در این مثال اعداد زوج می‌باشد.

متدهای Min و Max

متدهای Min و Max کوچک‌ترین و بزرگترین مقادیر موجود در یک آرایه را مشخص می‌کنند. نسخه‌های بدون پارامتر این دو متد این کار را به سادگی انجام می‌دهند :

int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 };

Console.WriteLine("Min = {0}\nMax = {1}", numbers.Min(), numbers.Max());

برای اشیاء پیچیده‌تری که هیچ پیاده سازی برای IComparable ندارند، می‌توان از یکی از سربارگذاری های این متدها استفاده کرد که اشیاء را بر اساس یکی از خصوصیات آنها مقایسه می‌کنند :

List<Person> people = GetPersonList(); //Assume the method returns a collection of Person objects

Console.WriteLine("Youngest Age is {0}", people.Min( p=>p.Age ));
Console.WriteLine("Oldest Age is {0}", people.Max( p=>p.Age ));

همانطور که در مثال بالا مشاهده می‌کنید ما لیستی از اشخاص داریم که متدهای Min و Max آن‌ها را بر اساس خاصیت Age شان مقایسه می‌کنند و کمترین و بالاترین سن آنها را مشخص می‌نمایند.

متد Average

متد Average برای به دست آوردن میانگین مقادیر عددی به کار می‌رود. این متد حاصل جمع تمام مقادیر عناصر را بر تعداد عناصر تقسیم می‌کند :

int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 };

Console.WriteLine("Average = {0}", numbers.Average());

مانند متدهای Min و Max دارای یک سربارگذاری است که اشیاء را براساس یک کلید یا خصوصیت مقایسه می‌کند.

List<Person> people = GetPersonList();

Console.WriteLine("Average age of all the persons");
Console.WriteLine("Average = {0}", people.Average( p => p.Age ));

همانطور که مشاهده می‌کنید در مثال بالا متد Average متوسط سن افراد را بر می‌گرداند.

متد Sum

این متد مجموع همه مقادیر یک مجموعه را بر می‌گرداند.

int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 };

Console.WriteLine("Sum = {0}", numbers.Sum);

این متد نیز دارای یک سربارگذاری است که یک خاصیت از مجموعه اشیاء را با هم جمع می‌کند.

List<Person> people = GetPersonList();

Console.WriteLine("Total age of all the persons");
Console.WriteLine("Total = {0}", people.Sum(p => p.Age));

در مثال بالا خاصیت Age همه افراد با هم جمع می‌شوند.

متد Aggregate

این متد نسخه انعطاف پذیرتر متد Sum است. به جای اینکه شما را محدود به جمع مقادیر یک مجموعه بکند، می‌توانید دو پارامتر برای آن تعریف کنید که اولین پارامتر، اولین عدد یا نتیجه قبل و دومین پارامتر عدد دومی باشد که قرار است در عملیات شرکت کند.

int[] numbers = { 1, 2, 3, 4, 5 };

Console.WriteLine( numbers.Aggregate( (n1, n2) => n1 + n2 ) );

این متد دارای دو پارامتر لامبدا در داخل بدنه خود است. ابتدا دو عدد از آرایه را به ان اضافه می‌کنیم. اولین عدد، عدد اول آرایه (1) و دومین عدد، عدد دوم آرایه (2) است. این دو مقدار با هم جمع می‌شوند و در n1 ذخیره می‌شوند. مقدار سوم (3) در n2 قرار می‌گیرد و با n1 که قبلاً جمع دو عدد قبلی در آن قرار گرفته است (3) جمع می‌شود. این کار تا آخرین عنصر آرایه ادامه می‌یابد. نتیجه نهایی همانند نتیجه‌ای است که متد Sum برمی گرداند یعنی جمع همه مقادیر. نکته مهمی که در مورد Aggregate وجود دارد این است که شما می‌توانید عملگری را که می‌خواهید در عملیات مورد استفاده قرار دهید را انتخاب کنید. در مثال زیر عملگر را به عملگر ضرب تغییر می‌دهیم نتیجه نهایی حاصلضرب مقادیر یعنی 120 خواهد شد :

int[] numbers = { 1, 2, 3, 4, 5 };

Console.WriteLine( numbers.Aggregate( (n1, n2) => n1 * n2 ) );

متد را می‌توان به صورت زیر پیچیده‌تر هم کرد :

int[] numbers = { 1, 2, 3, 4, 5 };

Console.WriteLine( numbers.Aggregate( (n1, n2) => (n1 / 2) + (n2 / 2) ) );

متد بالا قبل از جمع مقادیر ابتدا آنها را بر دو تقسیم می‌کند. متد Aggregate دارای سربارگذاری دیگری نیز هست که در آن یک مقدار ثابت را می‌توان به حاصل جمع مقادیر اضافه کرد :

int[] numbers = { 1, 2, 3, 4, 5 };

Console.WriteLine( numbers.Aggregate( 1, (n1 , n2) => n1 + n2 ));

حاصل جمع مقادیر آرایه 15 می‌شود و چون ما مقدار ثابت 1 را سربارگذاری متد Aggregate قرار داده‌ایم جمع نهایی 16 خواهد شد.

سومین سربارگذاری متد Aggregate آرگومان سومی را قبول می‌کند که برای قالب بندی نتیجه نهایی مورد استفاده قرار می‌گیرد :

 Console.WriteLine( numbers.Aggregate( 1, (n1, n2) => n1 + n2, 
                                      n => String.Format("{0:C}", n)));

استفاده از متدهای به هم پیوسته کمک زیادی به برنامه نویسان در کاهش مدت زمان برنامه نویسی می‌کند.