اپراتورهای مرتب سازی در LINQ

19 فروردین 1398
درسنامه درس 3 از سری آموزش LINQ
LINQ-Sorting-operators

با یکی دیگر از آموزش های LINQ در خدمت شما هستیم در این قسمت قصد داریم به بررسی اپراتور های Sorting بپردازیم.

sorting operators چیست؟

در LINQ متدهایی برای مرتب سازی و دسته بندی دنباله ای از اطلاعات وجود دارند که با استفاده از آن ها می توان اطلاعات را بر اساس ویژگی های خاصی دسته بندی کرد (صعودی یا نزولی).

انواع اپرتورهای مرتب سازی یا Sorting Operators عبارت اند از:

  • OrderBy
  • OrderByDescending
  • ThenBy
  • ThenByDescending
  • Reverse

موارد اول تا چهارم برای دسته بندی اطلاعات گرفته شده از منبع داده، بر اساس یک الگوی خاص استفاده می شوند و مورد پنجم، یعنی REVERSE کاربرد متفاوت و ساده ای دارد که در آخر با آن آشنا خواهیم شد.

متدهای مرتب سازی در LINQ کاملا شبیه به Order by در زبان SQL عمل می کنند فقط روش استفاده از آن ها کمی متفاوت است.

جدول زیر اطلاعات دقیق تری در مورد این اپراتور ها در اختیار شما قرار می دهد.

توضیحات اپراتور
این اپراتور اطلاعات را به صورت صعودی مرتب می کند OrderBy
این اپراتور اطلاعات را به صورت نزولی مرتب می کند OrderByDescending
این اپراتور برای مرتب سازی ثانویه به صورت صعودی استفاده می شود ThenBy
این اپراتور برای مرتب سازی ثانویه به صورت نزولی استفاده می شود ThenByDescending
این اپراتور برای برای برعکس کردن ترتیب عناصر در یک مجموعه استفاده می شود Reverse

متد OrderBy

با استفاده از این متد می توان مجموعه اطلاعات دریافت شده از منبع داده را به صورت صعودی مرتب سازی کرد. نوع اطلاعات مرتب شده می تواند عدد یا رشته یا هر نوع داده ای باشد.

الگوی استفاده از متد OrderBy به صورت زیر می باشد:

var studentname = Objstudent.OrderBy(x => x);

در عبارت Lambda نوشته شده در داخل متد OrderBy باید متغیری که قصد داریم مرتب سازی را بر اساس آن انجام دهی، انتخاب کنیم. مثالا x.name که مرتب سازی را بر اساس نام انجام می دهد.

برای آشنایی با نحوه ی به کار بردن OrderBy به مثال های زیر توجه کنید.

using System;
using System.Collections.Generic;
using System.Linq;
namespace Linqtutorials
{
    class Program
    {
        static void Main(string[] args)
        {

            String[] ArrayCountries = { "Iran", "Uk", "Usa", "China", "Germany", "Japan", "Albania" };
            var Countries = ArrayCountries.OrderBy(x =>x);
            foreach (var c in Countries)
            {
                Console.WriteLine(c);
            }
            Console.ReadLine();
        }
    }
}

در این مثال ساده یک آرایه تعریف شده که اعضای آن نام کشور های مختلف است و با استفاده از متد OrderBy قصد داریم آن ها را به ترتیب حروف ABC مرتب کنیم توجه داشته باشید که مرتب سازی با این متد به صورت پیش فرض، صعودی است.

مانند قبل، این کد را به صورت Query تغییر می دهیم:

var Countries = from co in ArrayCountries
orderby co
select co;
خروحی مثال اول-OrderBy
خروحی مثال اول- متد OrderBy

به مثال دوم از کاربرد OrderBy توجه کنید:

using System;
using System.Collections.Generic;
using System.Linq;
namespace Linqtutorials
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> Objstudent = new List<Student>()
            {
                new Student() { Name = "Suresh Dasari", Gender = "Male", Subjects = new List<string> { "Mathematics", "Physics" } },
                new Student() { Name = "Rohini Alavala", Gender = "Female", Subjects = new List<string> { "Entomology", "Botany" } },
                new Student() { Name = "Praveen Kumar", Gender = "Male", Subjects = new List<string> { "Computers", "Operating System", "Java" } },
                new Student() { Name = "Sateesh Chandra", Gender = "Male", Subjects = new List<string> { "English", "Social Studies", "Chemistry" } },
                new Student() { Name = "Madhav Sai", Gender = "Male", Subjects = new List<string> { "Accounting", "Charted" } }
            };
            var studentname = Objstudent.OrderBy(x => x.Name);
            foreach (var student in studentname)
            {
                Console.WriteLine(student.Name);
            }  
            Console.ReadLine();
        }
    }
    class Student
    {
        public string Name { get; set; } 
        public string Gender { get; set; }
        public List<string> Subjects { get; set; }
    }
}

در این مثال نیز یک List تعریف شده که اعضای آن از جنس کلاس Student هستند و قصد داریم نام هر دانشجو را به صورت صعودی مرتب کنیم برای این منظور از متد OrderBy استفاده کرده ایم که خروجی آن به صورت زیر است:

خروجی مثال دوم-OrderBy
خروجی مثال دوم - متد OrderBy

برای نوشتن کد به صورت Query تغییرات زیر را اعمال می کنیم:

var studentname = from x in Objstudent
orderby x.Name
select x;

متد OrderByDescending

کاربرد این متد دقیقا شبیه به OrderBy بوده فقط اطلاعات موجود را به صورت نزولی مرتب می کند.

دو مثال نوشته شده برای OrderBy را با استفاده از OrderByDescending پیاده سازی می کنیم تا با تفاوت آن ها بیشتر آشنا شوید و با مقایسه ی خروجی، کاربرد آن را به راحتی درک کنید.

using System;
using System.Collections.Generic;
using System.Linq;
namespace Linqtutorials
{
    class Program
    {
        static void Main(string[] args)
        {

            String[] ArrayCountries = { "Iran", "Uk", "Usa", "China", "Germany", "Japan", "Albania" };
            var Countries = ArrayCountries.OrderByDescending(x => x);
            foreach (var c in Countries)
            {
                Console.WriteLine(c);
            }
            Console.ReadLine();
        }
    }
خروجی مثال اول-OrderByDescending
خروجی مثال اول - متد OrderByDescending

خب برای نوشتن کد به صورت Query باید به صورت زیر عمل کنیم.

var Countries = from x in ArrayCountries
orderby x descending
select x;

در روش Query باید بعد از نوشتن OrderBy و نام مجموعه، نوع مرتب سازی آن را اعلام کنیم که اکر عبارتی نوشته نشود مرتب سازی به صورت صعودی انجام خواهد شد(حالت پیش فرض) اما اگر عبارت descending اعلام شود مرتب سازی به صورت نزولی انجام خواهد شد که شباهت بسیار زیاردی به زبان SQL دارد.

به مثال زیر توجه کنید:

using System;
using System.Collections.Generic;
using System.Linq;
namespace Linqtutorials
{
    class Program
    {
        static void Main(string[] args)
        {
            
            var studentname = Student.GetList().OrderByDescending(x => x.Name);
            foreach (var student in studentname)
            {
                Console.WriteLine(student.Name);
            }
            Console.ReadLine();
        }
    }
    class Student
    {
        public string Name { get; set; }
        public string Gender { get; set; }
        public List<string> Subjects { get; set; }

        public static List<Student> GetList()
        {
            List<Student> Objstudent = new List<Student>()
            {
                new Student() { Name = "Suresh Dasari", Gender = "Male", Subjects = new List<string> { "Mathematics", "Physics" } },
                new Student() { Name = "Rohini Alavala", Gender = "Female", Subjects = new List<string> { "Entomology", "Botany" } },
                new Student() { Name = "Praveen Kumar", Gender = "Male", Subjects = new List<string> { "Computers", "Operating System", "Java" } },
                new Student() { Name = "Sateesh Chandra", Gender = "Male", Subjects = new List<string> { "English", "Social Studies", "Chemistry" } },
                new Student() { Name = "Madhav Sai", Gender = "Male", Subjects = new List<string> { "Accounting", "Charted" } }
            };
            return Objstudent;
        }
    }
}

این مثال دقیقا همان مثال دوم OrderBy است، فقط پیاده سازی لیست را با استفاده از یک متد Static در داخل کلاس Student انجام دادیم. به نحوه ی فراخوانی متد Getlist و استفاده از OrderByDescending دقت کنید.

خروجی مثال دوم-OrderByDescending
خروجی مثال دوم - متد OrderByDescending

روش دوم پیاده سازی هم به صورت زیر انجام خواهد شد:

 var studentname = from stu in Student.GetList()
orderby stu.Name descending
select stu;

بار دیگر با دقت به نحوه ی فراخوانی متد GetList توجه کنید.

خروجی های دو متد را مقایسه کرده تا تفاوت ها و شباهت های این دو متد را درک کنید.

متد ThenBy

در LINQ، این متد مرتب سازی برای پیاده سازی چندین فیلد استفاده می شود و به طور پیش فرض پس از آن عملگر، عناصر را به ترتیب صعودی مرتب می کند. به طور کلی، در LINQ اپراتور ThenBy همراه با اپراتور OrderBy برای مرتب سازی بر روی چندین فیلد در لیست یا مجموعه استفاده می شود.

در عملیات مرتب سازی اگر به بیشتر از یک فیلد نیاز داشتیم باید از این اپراتور استفاده کنیم. توجه داشته باشید که این اپراتور بعد از OrderBy به کار می رود که به نوعی اپراتور ThenBy برای مرتب سازی ثانویه استفاده می شود.

الگوی استفاده از Hن به صورت زیر است:

var studentname = Objstudent.OrderBy(x => x).ThenBy(x => x);

به مثال های زیر توجه کنید:

using System;
using System.Collections.Generic;
using System.Linq;
namespace Linqtutorials
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            students.Add(new Student { Id = 1, Name = "ADAM ", Rank = 1, Age = 39 });
            students.Add(new Student { Id = 2, Name = "JACKSON ", Rank = 1, Age = 32 });
            students.Add(new Student { Id = 3, Name = "ELIZA ", Rank = 2, Age = 45 });
            students.Add(new Student { Id = 4, Name = "ZOE ", Rank = 2, Age = 39 });
            var studentsOrderByRank = students.OrderBy(x => x.Rank).ThenBy(x =>x.Age);
            Console.WriteLine("Sorted Students:");
            foreach (var student in studentsOrderByRank)
            {
                Console.WriteLine("Name={0} Age={1} Rank={2}",student.Name,student.Age,student.Rank);
            }
            Console.ReadLine();
        }
    }
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Rank { get; set; }
        public int Age { get; set; }
    }
}

هدف ما در این مثال مرتب سازی عناصر لیست بر اساس Rank و Age است. با دقت به خروجی توجه کنید، الویت اول ما برای مرتب سازی بر اساس Rank است و اولویت دوم بر اساس Age.

کدهای فوق را در ویرایشگر خود بنویسید و مراحل زیر را روی آن اعمال کنید تا کاربرد ThenBy را عمیقا درک کنید:

ابتدا برنامه را اجرا و به مرتب سازی ستون های Age و Rank دقت کنید.

حالا قسمت ThenBy را حذف کرده و دوباره خروجی را بررسی و با خروجی مرحله ی قبل مقایسه کنید.

مشاهده می کنید که در صورت به کار بردن ThenBy، ستون Age نیز مانند Rank به صورت صعودی (پیش فرض)  مرتب می شود اما در حالت دوم که ThenBy را حذف کردیم علی رغم این که ستون Rank به صورت صعودی مرتب سازی شده اما در ستون Age هیچ گونه مرتب سازی به چشم نمی خورد. مطمئنا تا الان متوجه شدید که کاربرد مرتب سازی ThenBy برای مواردی است که در یک ستون مقادیر تکراری داشته باشیم مثلا سن یا سال تولد یا نام دروس .

خب حالا کد را به صورت query پیاده سازی می کنیم:

var studentsOrderByRank = from student in students
orderby student.Rank, student.Age
select student;

خروحی این کد دقیقا شبیه به کد بالا است اما در آن اثری از ThenBy نیست. در روش query لازم نیست از ThenBy استفاده کنیم، فقط کافی است بعد از مرتب سازی اولیه با استفاده از کاراکتر  شروط مرتب سازی را از یکدیگر جدا کنیم. این روش کاملا مشابه زبان SQL است.

خروجی مثال -ThenBy
خروجی مثال - متد ThenBy

متد ThenByDescending

این متد کاملا شبیه به ThenBy بوده فقط اطلاعات را به صورت نزولی مرتب سازی می کند.

الگوی استفاده ار آن به صورت زیر است:

var studentname = Objstudent.OrderByDescending(x => x).ThenByDescending(x => x);

همان مثال ThenBy را برای این متد باز نویسی می کنیم:

using System;
using System.Collections.Generic;
using System.Linq;
namespace Linqtutorials
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            students.Add(new Student { Id = 1, Name = "ADAM ", Rank = 1, Age = 39 });
            students.Add(new Student { Id = 2, Name = "JACKSON ", Rank = 1, Age = 32 });
            students.Add(new Student { Id = 3, Name = "ELIZA ", Rank = 2, Age = 45 });
            students.Add(new Student { Id = 4, Name = "ZOE ", Rank = 2, Age = 39 });
            var studentsOrderByRank = students.OrderByDescending(x => x.Rank).ThenByDescending(x =>x.Age);
            Console.WriteLine("Sorted Students:");
            foreach (var student in studentsOrderByRank)
            {
                Console.WriteLine("Name={0} Age={1} Rank={2}",student.Name,student.Age,student.Rank);
            }
            Console.ReadLine();
        }
    }
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Rank { get; set; }
        public int Age { get; set; }
    }
}
خروجی-ThenByDescending
خروجی - متد ThenByDescending

برای پیاده سازی به صورت Query به شکل زیر عمل می کنیم:

var studentsOrderByRank = from stu in students
orderby stu.Rank descending, stu.Age descending
select stu;

به descending های استفاده شده در این روش دقت کنید که برای هر ستون لازم است نوع مرتب سازی به صورت جداگانه تعیین شود. در صورت عدم استفاده از descending اطلاعات به صورت صعودی مرتب سازی خواهد شد.

لازم به ذکر است که ThenByDescending می تواند بعد از OrderByDescending و OrderBy به کار رود. در این مثال برای این که تفاوت خروجی بر اساس نزولی بودن مشهود باشد از OrderByDescending استفاده کردیم.

متد Reverse

با استفاده از این متد می توان عناصر یک لیست یا مجموعه را به صورت برعکس مرتب کرد.

الگوی استفاده از آن به صورت زیر می باشد:

IEnumerable<Student> result = Students.Reverse();

به مثال زیر توجه کنید:

using System;
using System.Collections.Generic;
using System.Linq;
namespace Linqtutorials
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] number = { 10, 30, 45, 100, 700, 12, 50 };
            IEnumerable<int> num = number.Select(x =>x);
            IEnumerable<int> numReverse = number.Reverse<int>();
            Console.WriteLine("Before Reverse ");
            foreach (int item in num)
            {
                Console.Write(item +" ");
            }
            Console.WriteLine();
            Console.WriteLine("After Reverse ");
            foreach (int item in numReverse)
            {
                Console.Write(item + " ");
            }
            Console.ReadLine();
        }
    }

در این مثال عناصر یک آرایه int را قبل از Reverse و بعد از Reverse نشان داده ایم.

خروحی مثال -Reverse
خروحی مثال - متد Reverse

برای بازنویسی کد به صورت Query به روش زیر عمل می کنیم:

 IEnumerable<int> num = from x in number
select x;
 IEnumerable<int> numReverse = (from x in number
select x).Reverse<int>();

در query اول که مانند قبل یک select انجام شده، داده ها بدون تغییری در خروجی نشان داده می شوند، اما برای معکوس کردن مرتب سازی، علاوه بر اعمال یک select لازم است کلیه ی اطلاعات آماده شده برای نمایش در خروجی با استفاده از این متد معکوس شوند. به نحوه ی قرار گیری پرانتز ها و پیاده سازی متد Reverse دقت کنید.

این بخش از آموزش هم به پایان رسید. در جلسه ی بعدی آموزش، Set Operators را بررسی خواهم کرد.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش LINQ توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.