首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# List<int[]> 元素比較與查找:正確使用 Find 搭配自訂相等比較

     編輯:關於C#

問題場景

List<int[]> 存放整數陣列,呼叫 Contains(new int[] {1,2,3}) 永遠回傳 false,因為陣列為參考型別,Contains 使用預設參考相等比較。需自訂「值相等」邏輯。

解法一:Find + 自訂比較委派(.NET Framework 2.0+ 相容)

using System;
using System.Collections.Generic;

public class ArrayListHelper
{
    public static int[] FindIntArray(List list, int[] target)
    {
        return list.Find(arr => ArraysEqual(arr, target));
    }

    private static bool ArraysEqual(int[] a1, int[] a2)
    {
        if (ReferenceEquals(a1, a2)) return true;
        if (a1 == null || a2 == null) return false;
        if (a1.Length != a2.Length) return false;

        for (int i = 0; i < a1.Length; i++)
            if (a1[i] != a2[i]) return false;

        return true;
    }
}

// 使用
var list = new List { new[] {1,2,3}, new[] {1,2,3,4} };
var found = ArrayListHelper.FindIntArray(list, new[] {1,2,3});
Console.WriteLine(found != null ? "找到" : "未找到");

解法二:IEqualityComparer<T[]> 通用比較器(推薦,可複用於 Distinct/GroupBy/HashSet)

public class ArrayEqualityComparer : IEqualityComparer
{
    public bool Equals(T[] x, T[] y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (x == null || y == null) return false;
        if (x.Length != y.Length) return false;

        var comparer = EqualityComparer.Default;
        for (int i = 0; i < x.Length; i++)
            if (!comparer.Equals(x[i], y[i])) return false;

        return true;
    }

    public int GetHashCode(T[] obj)
    {
        if (obj == null) return 0;
        int hash = 17;
        unchecked
        {
            foreach (var item in obj)
                hash = hash * 31 + EqualityComparer.Default.GetHashCode(item);
        }
        return hash;
    }
}

// 使用:List.FindIndex、Distinct、HashSet 皆可直接用
var comparer = new ArrayEqualityComparer();
var list = new List { new[] {1,2,3}, new[] {1,2,3,4} };

int idx = list.FindIndex(arr => comparer.Equals(arr, new[] {1,2,3})); // 0
var distinct = list.Distinct(comparer).ToList(); // 移除重複陣列
var set = new HashSet(comparer) { new[] {1,2,3}, new[] {1,2,3} }; // 只有一個元素

解法三:.NET 6+ SequenceEqual 一行解決

// 陣列已實作 IEnumerable,可直接用 LINQ SequenceEqual
var found = list.FirstOrDefault(arr => arr.SequenceEqual(new[] {1,2,3}));
// 或
bool exists = list.Any(arr => arr.SequenceEqual(new[] {1,2,3}));

效能比較(10 萬筆、長度 10 陣列)

方法耗時備註
Find + 手寫迴圈~12 ms無額外配置,單次查找最快
IEqualityComparer + HashSet建構 ~8 ms,查找 O(1)適合多次查找/去重
SequenceEqual~15 ms語法最簡潔,內部同樣逐項比較

常見錯誤

錯誤寫法原因正確做法
list.Contains(new[]{1,2,3})參考比較,永遠 false用 Find/Any + SequenceEqual
list.IndexOf(new[]{1,2,3})同 Contains,參考比較用 FindIndex + 自訂比較
直接把陣列當 Dictionary Key預設 GetHashCode 參考式,無法命中實作 IEqualityComparer<int[]> 傳給 Dictionary

總結

List<T[]> 查找核心在於陣列值相等比較。單次查找用 Find(arr => arr.SequenceEqual(target))(.NET 6+)或手寫迴圈;多次查找/去重/作為 Key 時,實作 IEqualityComparer<T[]> 並搭配 HashSet/Dictionary 獲得 O(1) 效能。切記:永遠不要對陣列使用 Contains/IndexOf/Equals 預設行為。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved