List<int[]> 存放整數陣列,呼叫 Contains(new int[] {1,2,3}) 永遠回傳 false,因為陣列為參考型別,Contains 使用預設參考相等比較。需自訂「值相等」邏輯。
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 ? "找到" : "未找到");
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} }; // 只有一個元素
// 陣列已實作 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}));
| 方法 | 耗時 | 備註 |
|---|---|---|
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 預設行為。