Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

การลบค่าซ้ำใน List C# ด้วยเมธอด Distinct()

เมธอด 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 IEquatablelist.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