Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Tạo HashSet từ collection khác trong C#

HashSet<T> cung cấp constructor nhận IEnumerable<T> cho phép tạo HashSet mới từ một collection đã có (List, Array, HashSet khác...). Constructor này tự động loại bỏ các phần tử trùng lặp.

Ví dụ 1: Tạo HashSet<int> từ HashSet khác

using System;
using System.Collections.Generic;

public class Demo
{
    public static void Main()
    {
        HashSet<int> set1 = new HashSet<int>();
        set1.Add(100);
        set1.Add(200);
        set1.Add(300);

        Console.WriteLine("HashSet gốc (set1)...");
        foreach (int i in set1)
        {
            Console.WriteLine(i);
        }

        // Tạo HashSet mới từ set1
        HashSet<int> set2 = new HashSet<int>(set1);

        Console.WriteLine("\nHashSet tạo từ collection khác (set2)...");
        foreach (int i in set2)
        {
            Console.WriteLine(i);
        }
    }
}

Kết quả

HashSet gốc (set1)...
100
200
300

HashSet tạo từ collection khác (set2)...
100
200
300

Ví dụ 2: Tạo từ HashSet có phần tử trùng lặp

using System;
using System.Collections.Generic;

public class Demo
{
    public static void Main()
    {
        HashSet<string> set1 = new HashSet<string>();
        set1.Add("Jacob");
        set1.Add("Tom");
        set1.Add("Harry");
        set1.Add("Harry"); // Trùng lặp - bị bỏ qua
        set1.Add("Tom");   // Trùng lặp - bị bỏ qua
        set1.Add("Harry"); // Trùng lặp - bị bỏ qua

        Console.WriteLine("HashSet gốc (set1) - tự động loại trùng...");
        foreach (string i in set1)
        {
            Console.WriteLine(i);
        }

        // Tạo HashSet mới từ set1
        HashSet<string> set2 = new HashSet<string>(set1);

        Console.WriteLine("\nHashSet tạo từ collection khác (set2)...");
        foreach (string i in set2)
        {
            Console.WriteLine(i);
        }
    }
}

Kết quả

HashSet gốc (set1) - tự động loại trùng...
Jacob
Tom
Harry

HashSet tạo từ collection khác (set2)...
Jacob
Tom
Harry

Tạo HashSet từ các loại Collection khác

using System;
using System.Collections.Generic;
using System.Linq;

public class Demo
{
    public static void Main()
    {
        // 1. Từ List<T>
        List<int> list = new List<int> { 1, 2, 2, 3, 3, 3, 4 };
        HashSet<int> fromList = new HashSet<int>(list);
        // Kết quả: 1, 2, 3, 4

        // 2. Từ Array
        string[] array = { "A", "B", "A", "C", "B" };
        HashSet<string> fromArray = new HashSet<string>(array);
        // Kết quả: A, B, C

        // 3. Từ IEnumerable (LINQ)
        var numbers = Enumerable.Range(1, 10);
        HashSet<int> fromEnumerable = new HashSet<int>(numbers.Where(x => x % 2 == 0));
        // Kết quả: 2, 4, 6, 8, 10

        // 4. Từ HashSet khác (copy)
        HashSet<int> original = new HashSet<int> { 1, 2, 3 };
        HashSet<int> copy = new HashSet<int>(original);
    }
}

Constructor syntax

public HashSet(IEnumerable<T> collection);
  • Tham số: collection - bất kỳ IEnumerable<T>
  • Hành vi: Sao chép phần tử, tự động loại trùng lặp
  • Thứ tự: Không bảo đảm (HashSet unordered)
  • Null: Cho phép null nếu T là reference type

So sánh: Constructor vs ToHashSet() (LINQ)

List<int> list = new List<int> { 1, 2, 2, 3 };

// Cách 1: Constructor (từ .NET 2.0)
HashSet<int> set1 = new HashSet<int>(list);

// Cách 2: LINQ ToHashSet() (từ .NET 4.7.2 / .NET Core 2.0)
HashSet<int> set2 = list.ToHashSet();

// Cách 3: Với custom comparer
HashSet<string> set3 = new HashSet<string>(list.Select(x => x.ToString()), StringComparer.OrdinalIgnoreCase);

Lưu ý quan trọng

  • Constructor tạo bản sao độc lập - thay đổi set2 không ảnh hưởng set1
  • Phần tử trùng lặp trong source collection bị loại bỏ tự động
  • HashSet không giữ thứ tự - nếu cần thứ tự, dùng List<T> hoặc LinkedHashSet (Java) / custom
  • Hiệu năng: O(n) với n là số phần tử của collection nguồn
  • Cần using System.Collections.Generic

Custom Comparer

// Tạo HashSet case-insensitive từ List
List<string> names = new List<string> { "John", "JOHN", "john", "Mary" };
HashSet<string> uniqueNames = new HashSet<string>(names, StringComparer.OrdinalIgnoreCase);
// Kết quả: "John", "Mary" (chỉ 2 phần tử)