兩個集合 相等:元素值相同且各元素出現次數相同,順序可不同。
例:A={1,2,3,4,4,5}、B={1,4,4,2,3,5} → 相等。
public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2) {
if (list1.Count() != list2.Count()) return false;
var cnt = new Dictionary<T, int>();
foreach (var s in list1) {
if (cnt.ContainsKey(s)) cnt[s]++; else cnt.Add(s, 1);
}
foreach (var s in list2) {
if (cnt.ContainsKey(s)) cnt[s]--; else return false;
}
return cnt.Values.All(c => c == 0);
}
IEquatable<T> (預設型別均支援)。public static bool ScrambledEqualsUsingSequenceEqual<T>(IEnumerable<T> list1, IEnumerable<T> list2) {
return Enumerable.SequenceEqual(list1.OrderBy(t => t), list2.OrderBy(t => t));
}
OrderBy 排序 (O(N log N))。IComparer<T>。IEquatable<T> 並覆寫 GetHashCode。命名空間:Microsoft.VisualStudio.TestTools.UnitTesting (VS 單元測試) 或 NUnit.Framework。
定義:「兩集合元素值與數量相同,順序不拘」,完全符合本文定義。
[TestMethod]
public void TestCollectionEquality() {
var list1 = new[] { 1, 2, 3, 4, 4, 5 };
var list2 = new[] { 1, 4, 4, 2, 3, 5 };
CollectionAssert.AreEquivalent(list1, list2); // 通過
}
內部實現同樣採用 Dictionary 計數法,並加入空值檢查、參考相等快速判斷、集合介面優化等工程化細節:
private static bool HaveMismatchedElement(IEnumerable<T> first, IEnumerable<T> second) {
var firstCounts = GetElementCounts(first, out _);
var secondCounts = GetElementCounts(second, out _);
if (firstCounts.Count != secondCounts.Count) return true;
foreach (var kvp in firstCounts) {
if (firstCounts[kvp.Key] != secondCounts.GetValueOrDefault(kvp.Key)) return true;
}
return false;
}
| 場景 | 推薦方法 |
|---|---|
| 生產代碼、高效能、.NET 2.0+ | 方法一 |
| 生產代碼、.NET 3.5+、代碼簡潔優先 | 方法二 |
| 單元測試專案 | 方法三 |
| 需自訂相等比較器 | 方法一或二配合 IEqualityComparer |
集合相等性判斷本質是多重集合比較。Dictionary 計數法為通用高效基礎實現;SequenceEqual 排序法語法最簡潔;單元測試專案直接使用 CollectionAssert.AreEquivalent 即可。