Toán tử sắp xếp của LINQ

Một toán tử sắp xếp sẽ sắp xếp các phần tử của danh sách theo thứ tự tăng dần hoặc giảm dần. LINQ có các toán tử sắp xếp sau đây:

Toán tử Mô tả
OrderBy Sắp xếp các phần tử trong danh sách dựa trên trường được chỉ định. Trong đó toán tử orderby sắp xếp theo thứ tự tăng dần hoặc giảm dần còn phương thức mở rộng OrderBy sắp xếp theo thứ tự tăng dần.
OrderByDescending Sắp xếp các phần tử trong danh sách dựa trên trường được chỉ định theo thứ tự giảm dần. Chỉ có trong cú pháp phương thức, không có toán tử trong cú pháp truy vấn.
ThenBy Sắp xếp các phần tử trong danh sách dựa trên trường thứ hai theo thứ tự tăng dần. Chỉ có trong cú pháp phương thức, không có toán tử trong cú pháp truy vấn.
ThenByDescending Sắp xếp các phần tử trong danh sách dựa trên trường thứ hai theo thứ tự giảm dần. Chỉ có trong cú pháp phương thức, không có toán tử trong cú pháp truy vấn.
Reverse Sắp xếp các phần tử trong danh sách theo thứ tự ngược lại. Chỉ có trong cú pháp phương thức, không có toán tử trong cú pháp truy vấn.

Toán tử sắp xếp là một trong những toán tử truy vấn chuẩn của LINQ.

Toán tử truy vấn chuẩn của LINQ | Comdy
Các toán tử truy vấn chuẩn trong LINQ là các phương thức mở rộng cho các kiểu IEnumerable<T> và IQueryable<T>.

Toán tử sắp xếp OrderBy trong LINQ

OrderBy sắp xếp các giá trị của một danh sách theo thứ tự tăng dần hoặc giảm dần. LINQ hỗ trợ OderBy cả trong cú pháp truy vấn và cú pháp phương thức.

Mệnh đề orderby trong cú pháp truy vấn LINQ

Toán tử orderby trong cú pháp truy vấn LINQ sắp xếp danh sách theo thứ tự tăng dần theo mặc định vì từ khóa ascending là tùy chọn ở đây. Sử dụng từ khóa descending để sắp xếp danh sách theo thứ tự giảm dần.

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
	new Student() { StudentID = 1, StudentName = "John", Age = 18 },
	new Student() { StudentID = 2, StudentName = "Steve",  Age = 15 },
	new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
	new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
	new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 } 
};

// Sorts the studentList collection in ascending order
var orderByResult = from s in studentList
                    orderby s.StudentName
                    select s;

//Sorts the studentList collection in descending order
var orderByDescendingResult = from s in studentList 
                              orderby s.StudentName descending
                              select s;

Console.WriteLine("Ascending Order:");
foreach (var std in orderByResult)
{
    Console.WriteLine(std.StudentName);
}

Console.WriteLine("Descending Order:");
foreach (var std in orderByDescendingResult)
{
    Console.WriteLine(std.StudentName);
}

Đây là kết quả khi biên dịch và thực thi chương trình:

Ascending Order:
Bill
John
Ram
Ron
Steve
Descending Order:
Steve
Ron
Ram
John
Bill

Phương thức OrderBy trong cú pháp phương thức LINQ

Khác với mệnh đề orderby trong cú pháp truy vấn, phương thức OrderBy chỉ có thể sắp xếp các phần tử trong danh sách theo thứ tự tăng dần.

Phương thức mở rộng OrderBy có hai phương thức quá tải. Phương thức quá tải đầu tiên của OrderBy chấp nhận tham số kiểu delegate Func. Vì vậy, bạn cần truyền biểu thức lambda cho trường mà bạn muốn sắp xếp danh sách.

Phương thức quá tải thứ hai của OrderBy chấp nhận đối tượng của IComparer cùng với kiểu delegate Func, sử dụng so sánh tùy chỉnh để sắp xếp.

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector);

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector, 
    IComparer<TKey> comparer);

Ví dụ sau đây sắp xếp danh sách studentList theo thứ tự tăng dần của StudentName bằng phương thức mở rộng OrderBy.

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
	new Student() { StudentID = 1, StudentName = "John", Age = 18 },
	new Student() { StudentID = 2, StudentName = "Steve",  Age = 15 },
	new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
	new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
	new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 } 
};

// Sorts the studentList collection in ascending order
var studentsInAscOrder = studentList.OrderBy(s => s.StudentName);

foreach (var std in studentsInAscOrder)
{
    Console.WriteLine(std.StudentName);
}

Đây là kết quả khi biên dịch và thực thi chương trình:

Bill
John
Ram
Ron
Steve
Lưu ý: Trong cú pháp phương thức LINQ, phương thức OrderBy không hỗ trợ từ khóa descending để sắp xếp các phần tử trong danh sách theo thứ tự giảm dần. Sử dụng phương thức OrderByDescending để thực hiện điều này.

Toán tử sắp xếp OrderByDescending trong LINQ

Phương thức mở rộng OrderByDescending sắp xếp danh sách theo thứ tự giảm dần.

OrderByDescending chỉ hợp lệ với cú pháp phương thức. Nó không hợp lệ trong cú pháp truy vấn vì cú pháp truy vấn sử dụng toán tử orderby và các từ khóa ascending / descending để sắp xếp tăng dần / giảm dần như được trình bày ở trên.

Ví dụ dưới đây sắp xếp danh sách giảm dần theo tên:

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
	new Student() { StudentID = 1, StudentName = "John", Age = 18 },
	new Student() { StudentID = 2, StudentName = "Steve",  Age = 15 },
	new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
	new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
	new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 } 
};

//Sorts the studentList collection in descending order
var studentsInDescOrder = studentList.OrderByDescending(s => s.StudentName);

foreach (var std in studentsInDescOrder)
{
    Console.WriteLine(std.StudentName);
}

Đây là kết quả khi biên dịch và thực thi chương trình:

Steve
Ron
Ram
John
Bill

Toán tử sắp xếp ThenBy trong LINQ

Nếu như phương thức mở rộng OrderBy được sử dụng để sắp xếp danh sách theo thứ tự tăng dần của trường đầu tiên thì phương thức ThenBy cho phép sắp xếp danh sách theo thứ tự  tăng dần của trường tiếp theo nếu trường đầu tiên có giá trị giống nhau.

Phương thức mở rộng ThenBy chỉ hợp lệ với cú pháp phương thức LINQ.

Ví dụ dưới đây sắp xếp danh sách tăng dần theo tên và theo tuổi:

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
    new Student() { StudentID = 1, StudentName = "John", Age = 18 },
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 15 },
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
    new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 },
    new Student() { StudentID = 6, StudentName = "Ron" , Age = 18 },  
    new Student() { StudentID = 7, StudentName = "Ram" , Age = 14 }
};

var multiSortingResult = studentList.OrderBy(s => s.StudentName)
                                    .ThenBy(s => s.Age)
                                    .ToList();

foreach (var std in multiSortingResult)
{
    Console.WriteLine($"Name: {std.StudentName}, Age {std.Age}");
}

Đây là kết quả khi biên dịch và thực thi chương trình:

Name: Bill, Age 25
Name: John, Age 18
Name: Ram, Age 14
Name: Ram, Age 20
Name: Ron, Age 18
Name: Ron, Age 19
Name: Steve, Age 15

Toán tử sắp xếp ThenByDescending trong LINQ

Tương tự phương thức mở rộng ThenBy, phương thức mở rộng ThenByDescending cũng được sử dụng để sắp xếp danh sách giảm dần theo trường tiếp theo nếu trường đầu tiên có giá trị giống nhau.

Phương thức mở rộng ThenByDescending chỉ hợp lệ với cú pháp phương thức LINQ.

Ví dụ dưới đây sắp xếp danh sách tăng dần theo tên và giảm dần theo tuổi:

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
    new Student() { StudentID = 1, StudentName = "John", Age = 18 },
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 15 },
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
    new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 },
    new Student() { StudentID = 6, StudentName = "Ron" , Age = 18 },  
    new Student() { StudentID = 7, StudentName = "Ram" , Age = 14 }
};

var multiSortingResult = studentList.OrderBy(s => s.StudentName)
                                    .ThenByDescending(s => s.Age)
                                    .ToList();

foreach (var std in multiSortingResult)
{
    Console.WriteLine($"Name: {std.StudentName}, Age {std.Age}");
}

Đây là kết quả khi biên dịch và thực thi chương trình:

Name: Bill, Age 25
Name: John, Age 18
Name: Ram, Age 20
Name: Ram, Age 14
Name: Ron, Age 19
Name: Ron, Age 18
Name: Steve, Age 15

Toán tử sắp xếp Reverse trong LINQ

Phương thức mở rộng Reverse sắp xếp danh sách theo thứ tự ngược lại và nó chỉ hỗ trợ cú pháp phương thức LINQ.

Ví dụ dưới đây minh họa cách sử dụng toán tử sắp xếp Reverse trong LINQ:

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
	new Student() { StudentID = 1, StudentName = "John", Age = 18 },
	new Student() { StudentID = 2, StudentName = "Steve",  Age = 15 },
	new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
	new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
	new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 } 
};

var multiSortingResult = studentList.Reverse().ToList();

foreach (var std in multiSortingResult)
{
    Console.WriteLine($"Name: {std.StudentName}, Age {std.Age}");
}

Đây là kết quả khi biên dịch và thực thi chương trình:

Name: Ron, Age 19
Name: Ram, Age 20
Name: Bill, Age 25
Name: Steve, Age 15
Name: John, Age 18

Sắp xếp trên nhiều trường

Bạn có thể sắp xếp danh sách trên nhiều trường được phân tách bằng dấu phẩy.

Danh sách sẽ được sắp xếp dựa trên trường đầu tiên và sau đó nếu giá trị của trường thứ nhất giống nhau thì nó sẽ sử dụng trường thứ hai để sắp xếp, v.v.

Sử dụng cú pháp truy vấn LINQ

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
    new Student() { StudentID = 1, StudentName = "John", Age = 18 },
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 15 },
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
    new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 },
    new Student() { StudentID = 6, StudentName = "Ron" , Age = 18 },  
    new Student() { StudentID = 7, StudentName = "Ram" , Age = 14 }
};

var multiSortingResult = from s in studentList
                         orderby s.StudentName, s.Age 
                         select s;

var multiSortingMixResult = from s in studentList
                            orderby s.StudentName ascending, s.Age descending
                            select s;
                             
Console.WriteLine("Result 1:");
foreach (var std in multiSortingResult)
{
    Console.WriteLine($"Name: {std.StudentName}, Age {std.Age}");
}

Console.WriteLine("Result 2:");
foreach (var std in multiSortingMixResult)
{
    Console.WriteLine($"Name: {std.StudentName}, Age {std.Age}");
}

Đây là kết quả khi biên dịch và thực thi chương trình:

Result 1:
Name: Bill, Age 25
Name: John, Age 18
Name: Ram, Age 14
Name: Ram, Age 20
Name: Ron, Age 18
Name: Ron, Age 19
Name: Steve, Age 15
Result 2:
Name: Bill, Age 25
Name: John, Age 18
Name: Ram, Age 20
Name: Ram, Age 14
Name: Ron, Age 19
Name: Ron, Age 18
Name: Steve, Age 15

Sử dụng cú pháp phương thức LINQ

Sắp xếp trên nhiều trường trong cú pháp phương thức khác với cú pháp truy vấn. Nó sử dụng các phương thức mở rộng OrderBy / OrderByDescending để sắp xếp danh sách theo trường đầu tiên và ThenBy / ThenByDescending để sắp xếp danh sách theo trường tiếp theo.

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
    new Student() { StudentID = 1, StudentName = "John", Age = 18 },
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 15 },
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
    new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 },
    new Student() { StudentID = 6, StudentName = "Ron" , Age = 18 },  
    new Student() { StudentID = 7, StudentName = "Ram" , Age = 14 }
};

var multiSortingResult = studentList.OrderBy(s => s.StudentName)
                                    .ThenBy(s => s.Age)
                                    .ToList();

var multiSortingMixResult = studentList.OrderBy(s => s.StudentName)
                                       .ThenByDescending(s => s.Age)
                                       .ToList();
                             
Console.WriteLine("Result 1:");
foreach (var std in multiSortingResult)
{
    Console.WriteLine($"Name: {std.StudentName}, Age {std.Age}");
}

Console.WriteLine("Result 2:");
foreach (var std in multiSortingMixResult)
{
    Console.WriteLine($"Name: {std.StudentName}, Age {std.Age}");
}

Đây là kết quả khi biên dịch và thực thi chương trình:

Result 1:
Name: Bill, Age 25
Name: John, Age 18
Name: Ram, Age 14
Name: Ram, Age 20
Name: Ron, Age 18
Name: Ron, Age 19
Name: Steve, Age 15
Result 2:
Name: Bill, Age 25
Name: John, Age 18
Name: Ram, Age 20
Name: Ram, Age 14
Name: Ron, Age 19
Name: Ron, Age 18
Name: Steve, Age 15

Những điểm cần nhớ về toán tử sắp xếp của LINQ

  1. LINQ bao gồm năm toán tử sắp xếp: OrderBy, OrderByDescending, ThenBy, ThenByDescending và Reverse.
  2. Cú pháp truy vấn LINQ chỉ hỗ trợ mệnh đề orderby và có thể sắp xếp tăng dần hoặc giảm dần bằng cách sử dụng từ khóa 'ascending' và 'descending'.
  3. Cú pháp truy vấn LINQ hỗ trợ sắp xếp theo nhiều trường được phân tách bằng dấu phẩy và từ khóa sắp xếp 'ascending' hoặc 'descending'.
  4. Bạn phải sử dụng các phương thức OrderBy hoặc OrderByDescending kết hợp với ThenBy hoặc ThenByDescending để sắp xếp theo nhiều trường khác nhau khi sử dụng cú pháp phương thức LINQ.
  5. Sử dụng phương thức Reverse để sắp xếp đảo ngược danh sách sử dụng cú pháp phương thức LINQ.


Bài viết liên quan:

Bạn sẽ tìm hiểu một số truy vấn LINQ phức tạp trong hướng dẫn này.

Từ khóa let, into trong LINQ có tác dụng gì? Hướng dẫn khai báo và sử dụng từ khóa let, into trong LINQ.

Trì hoãn thực thi truy vấn LINQ là gì? Thực thi ngay lập tức truy vấn LINQ là gì? Làm sao để thực thi truy vấn LINQ.