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

Giao của hai mảng (Intersection) trong C#

Để lấy giao (intersection) của hai mảng (phần tử xuất hiện trong cả hai), dùng phương thức mở rộng Intersect từ namespace System.Linq.

Ví dụ cơ bản

using System;
using System.Linq;

class Program
{
    static void Main()
    {
        int[] arr1 = { 44, 76, 98, 34 };
        int[] arr2 = { 24, 98, 44, 55, 47, 86 };
        
        // Intersect: lấy phần tử chung (distinct)
        var intersection = arr1.Intersect(arr2);
        
        Console.WriteLine("Mảng 1: " + string.Join(", ", arr1));
        Console.WriteLine("Mảng 2: " + string.Join(", ", arr2));
        Console.WriteLine("Giao (Intersect): " + string.Join(", ", intersection));
        
        // Kết quả: 44, 98 (thứ tự theo arr1, distinct)
    }
}

Kết quả

Mảng 1: 44, 76, 98, 34
Mảng 2: 24, 98, 44, 55, 47, 86
Giao (Intersect): 44, 98

Các biến thể

1. Intersect với IEqualityComparer (so sánh tùy chỉnh)

var intersection = arr1.Intersect(arr2, StringComparer.OrdinalIgnoreCase); // Cho string

2. IntersectBy (NET 6+) - Giao theo key selector

var people1 = new[] { new { Id = 1, Name = "A" }, new { Id = 2, Name = "B" } };
var people2 = new[] { new { Id = 2, Name = "B2" }, new { Id = 3, Name = "C" } };

// Giao theo Id
var common = people1.IntersectBy(people2.Select(p => p.Id), p => p.Id);
// Kết quả: { Id=2, Name="B" } (lấy từ people1)

3. Giữ trùng lặp (Intersect không distinct) - Custom

// Intersect mặc định distinct. Muốn giữ duplicate:
var multisetIntersect = arr1
    .GroupBy(x => x)
    .Join(arr2.GroupBy(x => x), 
          g => g.Key, g => g.Key,
          (g1, g2) => g1.Key)
    .SelectMany(k => Enumerable.Repeat(k, Math.Min(
        arr1.Count(x => x == k), 
        arr2.Count(x => x == k))));

So sánh với các phép tập hợp khác

Phép toánPhương thức LINQMô tả
Giao (Intersection)IntersectPhần tử có trong CẢ HAI
Hợp (Union)UnionPhần tử có trong ÍT NHẤT MỘT (distinct)
Hiệu (Difference)ExceptPhần tử có trong THỨ NHẤT nhưng KHÔNG trong thứ hai
Hiệu đối xứngSymmetricExcept (NET 7+)Phần tử chỉ có trong MỘT trong hai

Lưu ý

  • Intersect trả về IEnumerable<T> (deferred execution).
  • Kết quả distinct (loại trùng) và giữ thứ tự xuất hiện đầu tiên trong mảng thứ nhất.
  • Cho mảng lớn, cân nhắc HashSet<T> để O(n+m) thay vì O(n*m) naive.