การหา **Common Elements** (สมาชิกร่วม) ระหว่างสอง List ใน C# ทำได้ง่ายด้วย LINQ Method Intersect() ซึ่งคืนค่า Set Intersection (ไม่ซ้ำกัน) โดย Default ใช้ Default Equality Comparer
Syntax
var common = list1.Intersect(list2); // คืน IEnumerable
ตัวอย่างพื้นฐาน
using System;
using System.Linq;
using System.Collections.Generic;
namespace Demo {
class Program {
static void Main(string[] args) {
List list1 = new List { 40, 20, 60, 3, 55 };
List list2 = new List { 20, 70, 55, 80 };
Console.WriteLine("Common elements:");
foreach (int value in list1.Intersect(list2)) {
Console.WriteLine(value);
}
}
}
}
ผลลัพธ์
Common elements:
20
55
รายละเอียดการทำงาน
- Set Operation: คืนค่า Unique Values เท่านั้น (Duplicates ถูกลบ)
- Order Preserved: รักษาลำดับจาก List แรก (
list1) - Deferred Execution: Query ไม่รันทันที รันตอน Iterate (foreach, ToList)
- Equality Comparer: ใช้
EqualityComparer<T>.Default(สำหรับ Custom Class ต้อง ImplementIEquatable<T>หรือ OverrideEquals/GetHashCode)
ตัวอย่างขั้นสูง
1. กับ Custom Class (ต้อง Implement IEquatable)
public class Product : IEquatable {
public int Id { get; set; }
public string Name { get; set; }
public bool Equals(Product other) {
return other != null && Id == other.Id;
}
public override bool Equals(object obj) => Equals(obj as Product);
public override int GetHashCode() => Id.GetHashCode();
}
var list1 = new List { new Product { Id = 1 }, new Product { Id = 2 } };
var list2 = new List { new Product { Id = 2 }, new Product { Id = 3 } };
var common = list1.Intersect(list2); // Product Id=2
2. ใช้ Custom Comparer
var common = list1.Intersect(list2, new ProductNameComparer());
public class ProductNameComparer : IEqualityComparer {
public bool Equals(Product x, Product y) => x?.Name == y?.Name;
public int GetHashCode(Product obj) => obj?.Name?.GetHashCode() ?? 0;
}
3. IntersectWith (Mutable - แก้ไข List ต้นฉบับ)
var list1 = new List { 1, 2, 3, 4, 5 };
var list2 = new List { 3, 4, 5, 6, 7 };
list1.IntersectWith(list2); // list1 กลายเป็น { 3, 4, 5 } - แก้ไข In-place
// ต้องใช้ using System.Collections.Generic; และ List ต้องเป็น HashSet หรือ SortedSet
// จริงๆ List ไม่มี IntersectWith - ต้อง Convert เป็น HashSet ก่อน
4. เก็บ Duplicate ด้วย (Intersect แบบเก็บซ้ำ)
// Intersect มาตรฐาน: {1,2,2,3} ∩ {2,2,4} = {2}
// ถ้าต้องการเก็บ Duplicate ตามจำนวนน้อยที่สุด:
var list1 = new List { 1, 2, 2, 3 };
var list2 = new List { 2, 2, 4 };
var commonWithDuplicates = list1
.GroupBy(x => x)
.Join(list2.GroupBy(x => x),
g => g.Key, g => g.Key,
(g1, g2) => g1.Take(Math.Min(g1.Count(), g2.Count())))
.SelectMany(x => x);
// Result: {2, 2}
Related Set Operations
| Operation | Method | คำอธิบาย |
|---|---|---|
| Intersection | Intersect |
สมาชิกร่วม (A ∩ B) |
| Union | Union |
รวมทั้งหมด ไม่ซ้ำ (A ∪ B) |
| Difference | Except |
อยู่ใน A แต่ไม่อยู่ใน B (A - B) |
| Symmetric Difference | Union + Except |
อยู่ในอันใดอันหนึ่งแต่ไม่ใช่ทั้งคู่ |
Performance
- Time: O(n + m) - ใช้ HashSet ภายใน
- Space: O(min(n, m)) - เก็บ HashSet ของ List ที่เล็กกว่า
- เร็วกว่า Nested Loop (O(n×m)) มากสำหรับ List ใหญ่