เมธอด Distinct() ใน System.Linq ใช้ลบองค์ประกอบที่ซ้ำกันออกจากลำดับ คืนลำดับใหม่ที่มีเฉพาะค่าที่ไม่ซ้ำกัน (Unique values) ใช้ได้กับทุกชนิดที่ implement IEquatable<T> หรือมี EqualityComparer
รูปแบบการใช้งาน
List numbers = new List { 10, 20, 30, 20, 10, 40 };
List unique = numbers.Distinct().ToList(); // { 10, 20, 30, 40 }
โค้ดตัวอย่างสมบูรณ์
using System;
using System.Collections.Generic;
using System.Linq;
public class Demo
{
public static void Main()
{
List numbers = new List { 10, 20, 30, 40, 50, 30, 40, 50 };
Console.WriteLine("ลิสต์ต้นฉบับ:");
Console.WriteLine(string.Join(", ", numbers));
// ลบค่าซ้ำ
List distinct = numbers.Distinct().ToList();
Console.WriteLine("\nหลังลบค่าซ้ำ (Distinct):");
Console.WriteLine(string.Join(", ", distinct));
// ตัวอย่างกับ String (Case-sensitive)
Console.WriteLine("\n--- String (Case-sensitive) ---");
List words = new List { "Apple", "apple", "BANANA", "Banana", "Cherry" };
var distinctWords = words.Distinct().ToList();
Console.WriteLine($"ต้นฉบับ: {string.Join(", ", words)}");
Console.WriteLine($"Distinct: {string.Join(", ", distinctWords)}"); // ทั้งหมดไม่ซ้ำ (Case-sensitive)
// Case-insensitive Distinct
var distinctIgnoreCase = words.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
Console.WriteLine($"Distinct (IgnoreCase): {string.Join(", ", distinctIgnoreCase)}"); // Apple, BANANA, Cherry
// ตัวอย่างกับ Object (ต้อง Implement IEquatable หรือ ใช้ IEqualityComparer)
Console.WriteLine("\n--- Object แบบกำหนดเอง ---");
var people = new List
{
new Person("John", 25),
new Person("Jane", 30),
new Person("John", 25), // Duplicate
new Person("Bob", 35)
};
var uniquePeople = people.Distinct(new PersonComparer()).ToList();
Console.WriteLine($"คนไม่ซ้ำ: {uniquePeople.Count} คน");
foreach (var p in uniquePeople) Console.WriteLine($" {p}");
}
}
// Class สำหรับทดสอบ
public class Person
{
public string Name { get; }
public int Age { get; }
public Person(string name, int age) { Name = name; Age = age; }
public override string ToString() => $"{Name} ({Age})";
}
// Custom Comparer สำหรับ Person
public class PersonComparer : IEqualityComparer
{
public bool Equals(Person x, Person y) =>
x?.Name == y?.Name && x?.Age == y?.Age;
public int GetHashCode(Person obj) =>
HashCode.Combine(obj?.Name, obj?.Age);
}
ผลลัพธ์
ลิสต์ต้นฉบับ:
10, 20, 30, 40, 50, 30, 40, 50
หลังลบค่าซ้ำ (Distinct):
10, 20, 30, 40, 50
--- String (Case-sensitive) ---
ต้นฉบับ: Apple, apple, BANANA, Banana, Cherry
Distinct: Apple, apple, BANANA, Banana, Cherry
Distinct (IgnoreCase): Apple, BANANA, Cherry
--- Object แบบกำหนดเอง ---
คนไม่ซ้ำ: 3 คน
John (25)
Jane (30)
Bob (35)
Distinct() แบบต่างๆ
| เมธอด | ใช้เมื่อ | ตัวอย่าง |
|---|---|---|
Distinct() | ชนิดพื้นฐาน (int, string, ฯลฯ) หรือ Implement IEquatable | list.Distinct() |
Distinct(comparer) | ต้องการกำหนดกฎการเปรียบเทียบเอง | list.Distinct(StringComparer.OrdinalIgnoreCase) |
DistinctBy(selector) | .NET 6+ ต้องการ Distinct ตาม Property เฉพาะ | people.DistinctBy(p => p.Email) |
DistinctBy (.NET 6+) - แนะนำสำหรับ Object
// .NET 6+ - ไม่ต้องเขียน IEqualityComparer
var uniqueByEmail = people.DistinctBy(p => p.Email).ToList();
var uniqueByName = people.DistinctBy(p => p.Name).ToList();
// หลาย Property (ใช้ Tuple)
var uniqueByNameAge = people.DistinctBy(p => (p.Name, p.Age)).ToList();
ประสิทธิภาพ
- Time Complexity: O(n) ใช้ HashSet ภายใน
- Space Complexity: O(n) สำหรับ HashSet
- รักษาลำดับเดิมของค่าที่ปรากฏครั้งแรก (Stable)
ข้อควรระวัง
Distinct()คืนIEnumerable<T>- ต้อง.ToList()หรือ.ToArray()หากต้องการ List/Array- สำหรับ Class/Record ต้อง Implement
IEquatable<T>หรือส่งIEqualityComparer<T>เข้าไป Record(C# 9+) มี Equality โดยอัตโนมัติ - ใช้Distinct()ได้เลย- Case-sensitive โดยค่าเริ่มต้น - ใช้
StringComparerสำหรับ Case-insensitive