Tổng quan 3 toán tử Set Operations
| Toán tử | Mô tả | Kết quả |
| Union | Hợp hai tập hợp, loại bỏ trùng lặp | Distinct elements từ cả hai |
| Intersect | Giao hai tập hợp | Phần tử có trong CẢ HAI |
| Except | Hiệu hai tập hợp | Phần tử chỉ có trong THỨ NHẤT |
Ví dụ cơ bản với Array
using System;
using System.Linq;
class Program
{
static void Main()
{
int[] set1 = { 1, 2, 3, 4 };
int[] set2 = { 2, 4, 7 };
// Union: 1, 2, 3, 4, 7
var union = set1.Union(set2);
// Intersect: 2, 4
var intersect = set1.Intersect(set2);
// Except (set1 - set2): 1, 3
var except = set1.Except(set2);
Console.WriteLine("Union: " + string.Join(", ", union));
Console.WriteLine("Intersect: " + string.Join(", ", intersect));
Console.WriteLine("Except: " + string.Join(", ", except));
}
}
Kết quả
Union: 1, 2, 3, 4, 7
Intersect: 2, 4
Except: 1, 3
Ví dụ với Object Complex (Cần IEqualityComparer)
class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
class ProductComparer : IEqualityComparer
{
public bool Equals(Product x, Product y)
{
if (x is null || y is null) return false;
return x.Id == y.Id; // So sánh theo Id
}
public int GetHashCode(Product obj)
{
return obj.Id.GetHashCode();
}
}
class Program
{
static void Main()
{
var list1 = new List
{
new Product { Id = 1, Name = "Laptop", Price = 1000 },
new Product { Id = 2, Name = "Mouse", Price = 25 },
new Product { Id = 3, Name = "Keyboard", Price = 75 }
};
var list2 = new List
{
new Product { Id = 2, Name = "Mouse", Price = 25 },
new Product { Id = 3, Name = "Keyboard Pro", Price = 120 },
new Product { Id = 4, Name = "Monitor", Price = 300 }
};
var comparer = new ProductComparer();
// Union: distinct by Id
var union = list1.Union(list2, comparer);
// Intersect: Id 2, 3
var intersect = list1.Intersect(list2, comparer);
// Except: Id 1 (chỉ có trong list1)
var except = list1.Except(list2, comparer);
}
}
Union vs Concat
var a = new[] { 1, 2, 3 };
var b = new[] { 3, 4, 5 };
// Union: Loại trùng lặp
a.Union(b); // { 1, 2, 3, 4, 5 }
// Concat: Giữ trùng lặp
a.Concat(b); // { 1, 2, 3, 3, 4, 5 }
Except vs Where Not Contains
// Except - Set based, hiệu quả hơn
var except = list1.Except(list2, comparer);
// Where + Contains - Chậm hơn cho collection lớn
var whereNotIn = list1.Where(x => !list2.Contains(x, comparer));
Distinct - Toán tử liên quan
// Loại bỏ trùng lặp trong một collection
var numbers = new[] { 1, 2, 2, 3, 3, 3, 4 };
var distinct = numbers.Distinct(); // { 1, 2, 3, 4 }
// Distinct với comparer
var distinctProducts = products.Distinct(new ProductComparer());
Hiệu năng và Lưu ý
- Union/Intersect/Except sử dụng
HashSet nội bộ → O(n + m) average.
- Yêu cầu
GetHashCode() và Equals() được implement đúng (cho custom types).
- Trả về
IEnumerable<T> - deferred execution.
- Giữ thứ tự xuất hiện của collection đầu tiên (stable).
Overload với IEqualityComparer
// Tất cả 3 toán tử đều có overload nhận comparer
source.Union(other, comparer);
source.Intersect(other, comparer);
source.Except(other, comparer);
source.Distinct(comparer);
Ứng dụng thực tế
- Union: Gộp danh sách user từ nhiều nguồn, loại trùng.
- Intersect: Tìm user có quyền truy cập CẢ HAI hệ thống.
- Except: Tìm user đã xóa (có trong old list nhưng không có trong new list).
- Distinct: Làm sạch dữ liệu nhập vào.