Toán tử tập hợp trong LINQ
Bảng sau liệt kê tất cả các toán tử tập hợp có sẵn trong LINQ.
Phương thức | Mô tả |
---|---|
Distinct | Trả về các phần tử khác nhau từ một danh sách. |
Except | Trả về các phần tử của một danh sách không xuất hiện trong danh sách thứ hai. |
Intersect | Trả về giao của hai danh sách, có nghĩa là các phần tử cùng xuất hiện trong cả hai danh sách. |
Union | Trả về các phần tử duy nhất từ hai danh sách, có nghĩa là các phần tử duy nhất xuất hiện ở một trong hai danh sách. |
Toán tử tập hợp là một trong những toán tử truy vấn chuẩn của LINQ.
Hình dưới đây minh họa cách mỗi toán tử tập hợp hoạt động trên các bộ sưu tập:
Phương thức Distinct trong LINQ
Phương thức mở rộng Distinct trả về một tập hợp các phần tử duy nhất từ danh sách đã cho.
Ví dụ dưới đây minh họa sử dụng phương thức Distinct trong LINQ:
IList<string> strList = new List<string>() { "One", "Two", "Three", "Two", "Three" };
IList<int> intList = new List<int>() { 1, 2, 3, 2, 4, 4, 3, 5 };
var distinctList1 = strList.Distinct();
foreach(var str in distinctList1)
{
Console.WriteLine(str);
}
var distinctList2 = intList.Distinct();
foreach(var i in distinctList2)
{
Console.WriteLine(i);
}
Đây là kết quả khi biên dịch và thực thi chương trình:
One
Two
Three
1
2
3
4
5
Phương thức mở rộng Distinct không so sánh giá trị của các đối tượng kiểu phức tạp. Bạn cần triển khai interface IEqualityComparer<T>
để so sánh giá trị của các kiểu phức tạp.
Trong ví dụ sau, lớp StudentComparer
triển khai interface IEqualityComparer<Student>
để so sánh các đối tượng Student
trong danh sách.
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public int Age { get; set; }
}
class StudentComparer : IEqualityComparer<Student>
{
public bool Equals(Student x, Student y)
{
return x.StudentID == y.StudentID &&
x.StudentName.ToLower() == y.StudentName.ToLower();
}
public int GetHashCode(Student obj)
{
return obj.StudentID.GetHashCode();
}
}
Bây giờ, bạn có thể truyền một đối tượng của lớp StudentComparer
trên làm tham số trong phương thức Distinct để so sánh các đối tượng Student
như dưới đây.
Ví dụ dưới đây minh họa sử dụng lớp StudentComparer làm đối số cho phương thức Distinct trong LINQ:
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 = 3, StudentName = "Bill", Age = 25 },
new Student() { StudentID = 3, StudentName = "Bill", Age = 25 },
new Student() { StudentID = 3, StudentName = "Bill", Age = 25 },
new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 }
};
var distinctStudents = studentList.Distinct(new StudentComparer());
foreach(Student std in distinctStudents)
{
Console.WriteLine(std.StudentName);
}
Đây là kết quả khi biên dịch và thực thi chương trình:
John
Steve
Bill
Ron
Lưu ý: Phương thức mở rộng Distinct không hỗ trợ cú pháp truy vấn trong LINQ.
Phương thức Except trong LINQ
Phương thức mở rộng Except yêu cầu đầu vào là hai danh sách. Nó trả về một danh sách mới với các phần tử từ danh sách đầu tiên không tồn tại trong danh sách thứ hai.
Ví dụ dưới đây minh họa sử dụng phương thức Except trong LINQ:
IList<string> strList1 = new List<string>() {"One", "Two", "Three", "Four", "Five" };
IList<string> strList2 = new List<string>() {"Four", "Five", "Six", "Seven", "Eight"};
var result = strList1.Except(strList2);
foreach(string str in result)
{
Console.WriteLine(str);
}
Đây là kết quả khi biên dịch và thực thi chương trình:
One
Two
Three
Tương tự như phương thức Distinct, phương thức mở rộng Except cũng không trả về kết quả chính xác cho các danh sách có kiểu phức tạp. Bạn cần triển khai interface IEqualityComparer<T>
để có được kết quả chính xác khi sử dụng phương thức Except.
Bạn có thể sử dụng lại lớp StudentComparer được định nghĩa ở phương thức Distinct cho phương thức mở rộng Except để có kết quả chính xác.
Ví dụ dưới đây minh họa sử dụng lớp StudentComparer làm đối số cho phương thức Except trong LINQ:
IList<Student> studentList1 = 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 = 5, StudentName = "Ron" , Age = 19 }
};
IList<Student> studentList2 = new List<Student>()
{
new Student() { StudentID = 3, StudentName = "Bill", Age = 25 },
new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 }
};
var resultedCol = studentList1.Except(studentList2, new StudentComparer());
foreach(Student std in resultedCol)
{
Console.WriteLine(std.StudentName);
}
Đây là kết quả khi biên dịch và thực thi chương trình:
John
Steve
Lưu ý: Phương thức mở rộng Except không hỗ trợ cú pháp truy vấn trong LINQ.
Phương thức Intersect trong LINQ
Phương thức mở rộng Intersect yêu cầu đầu vào là hai danh sách. Nó trả về một danh sách mới với các phần tử tồn tại trong cả hai danh sách.
Ví dụ dưới đây minh họa sử dụng phương thức Intersect trong LINQ:
IList<string> strList1 = new List<string>() {"One", "Two", "Three", "Four", "Five" };
IList<string> strList2 = new List<string>() {"Four", "Five", "Six", "Seven", "Eight"};
var result = strList1.Intersect(strList2);
foreach(string str in result)
{
Console.WriteLine(str);
}
Đây là kết quả khi biên dịch và thực thi chương trình:
Four
Five
Tương tự như phương thức Distinct và Except, phương thức mở rộng Intersect cũng không trả về kết quả chính xác cho các danh sách có kiểu phức tạp. Bạn cần triển khai interface IEqualityComparer<T>
để có được kết quả chính xác khi sử dụng phương thức Intersect.
Bạn có thể sử dụng lại lớp StudentComparer được định nghĩa ở phương thức Distinct cho phương thức mở rộng Intersect để có kết quả chính xác.
Ví dụ dưới đây minh họa sử dụng lớp StudentComparer làm đối số cho phương thức Intersect trong LINQ:
IList<Student> studentList1 = 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 = 5, StudentName = "Ron" , Age = 19 }
};
IList<Student> studentList2 = new List<Student>()
{
new Student() { StudentID = 3, StudentName = "Bill", Age = 25 },
new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 }
};
var resultedCol = studentList1.Intersect(studentList2, new StudentComparer());
foreach(Student std in resultedCol)
{
Console.WriteLine(std.StudentName);
}
Đây là kết quả khi biên dịch và thực thi chương trình:
Bill
Ron
Lưu ý: Phương thức mở rộng Intersect không hỗ trợ cú pháp truy vấn trong LINQ.
Phương thức Union trong LINQ
Phương thức mở rộng Union yêu cầu đầu vào là hai danh sách. Nó trả về một danh sách mới với các phần tử khác nhau ở trong cả hai danh sách.
Ví dụ dưới đây minh họa sử dụng phương thức Union trong LINQ:
IList<string> strList1 = new List<string>() {"One", "Two", "Three", "Four", "Five", "Six" };
IList<string> strList2 = new List<string>() {"Four", "Five", "Six", "Seven", "Eight"};
var result = strList1.Union(strList2);
foreach(string str in result)
{
Console.WriteLine(str);
}
Đây là kết quả khi biên dịch và thực thi chương trình:
One
Two
Three
Four
Five
Six
Seven
Eight
Tương tự như phương thức Distinct, Except và Intersect, phương thức mở rộng Union cũng không trả về kết quả chính xác cho các danh sách có kiểu phức tạp. Bạn cần triển khai interface IEqualityComparer<T>
để có được kết quả chính xác khi sử dụng phương thức Union.
Bạn có thể sử dụng lại lớp StudentComparer được định nghĩa ở phương thức Distinct cho phương thức mở rộng Union để có kết quả chính xác.
Ví dụ dưới đây minh họa sử dụng lớp StudentComparer làm đối số cho phương thức Union trong LINQ:
IList<Student> studentList1 = 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 = 5, StudentName = "Ron" , Age = 19 }
};
IList<Student> studentList2 = new List<Student>()
{
new Student() { StudentID = 3, StudentName = "Bill", Age = 25 },
new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 },
new Student() { StudentID = 6, StudentName = "July" , Age = 18 }
};
var resultedCol = studentList1.Union(studentList2, new StudentComparer());
foreach(Student std in resultedCol)
{
Console.WriteLine(std.StudentName);
}
Đây là kết quả khi biên dịch và thực thi chương trình:
John
Steve
Bill
Ron
July
Lưu ý: Phương thức mở rộng Union không hỗ trợ cú pháp truy vấn trong LINQ.