![](/img/trans.png)
[英]Compare two lists, where order doesn't matter, using IEqualityComparer
[英]Custom IEqualityComparer to get distinct objects from two lists faster than using .Where() + .Any()
所以我有兩個對象列表,對象具有多個字段,但是我只想基於其中兩個來區分它們。
為了給您提供圖片,對象KeyAndValue由字段Key和Tag組成,因此:
list1 = { obj1(key=1,tag=A), obj2(key=2,tag=A) }
list2 = { obj3(key=1,tag=A), obj4(key=2,tag=B) }
我目前正在使用:
list1.Where(x => !list2.Any(y => y.key == x.key)).ToList();
正確的結果是:obj1,obj2和obj4,因為obj3與obj1具有相同的鍵和標記
我要完成的工作是加快此過程,因為處理許多對象需要很長時間。 我發現自定義IEqualityComparer可以在這里提供幫助,因此我根據MS Specification編寫了自己的代碼,如下所示:
class KeyComparer : IEqualityComparer<KeyAndValue>
{
public bool Equals(KeyAndValue x, KeyAndValue y)
{
if (Object.ReferenceEquals(x, y))
return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
return x.key == y.key && x.tag == y.tag;
}
public int GetHashCode(KeyAndValue keyAndValue)
{
if (Object.ReferenceEquals(keyAndValue, null))
return 0;
int hashKeyAndValueKey = keyAndValue.key == null ? 0 : keyAndValue.key.GetHashCode();
int hashKeyAndValueTag = keyAndValue.tag == null ? 0 : keyAndValue.tag.GetHashCode();
return hashKeyAndValueKey ^ hashKeyAndValueTag;
}
}
我這樣使用它:
list1.Except(list2, new KeyComparer()).ToList();
不幸的是,它僅從list2中刪除重復項。 似乎它甚至都沒有觸及list1,而且我不知道這是我的自定義比較器的問題,還是我使用它的方式,或者我應該使用其他方法。 我一直在尋找其他問題,但找不到有效的答案(或至少我實際上知道如何正確實施的答案)。
我認為您不需要Except
。 您想兩者都有不同的價值嗎?
var distinctValues = list1.Union(list2).Distinct();
您需要在KeyAndValue
實現GetHashCode
/ Equals
或使用比較器通過鍵和值比較對象。
(舊東西在下面)
不知道我是否正確理解了這個問題。 可能是您不認識到,除了創建一個新的IEnumerable並ToList一個新的List之外?
嘗試:
var list1AdditionalItems = list1.Except(list2, new KeyComparer()).ToList();
可能還有:
var list2AdditionalItems = list2.Except(list1, new KeyComparer()).ToList();
另一個觀察。 在此代碼中:
list1.Where(x => !list2.Any(y => y.key == x.key)).ToList();
您只需檢查密鑰。 如果您想要這種行為,則應相應地編寫比較器:
class KeyComparer : IEqualityComparer<KeyAndValue>
{
public bool Equals(KeyAndValue x, KeyAndValue y)
{
if (ReferenceEquals(x, y))
return true;
if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
return false;
return x.key == y.key;
}
public int GetHashCode(KeyAndValue keyAndValue)
{
if (ReferenceEquals(keyAndValue, null))
return 0;
return keyAndValue.key == null ? 0 : keyAndValue.key.GetHashCode();
}
}
最后但並非最不重要的一點:當您需要性能時,請考慮使用字典。
正如Stefan Steinegger(在此我非常感謝所付出的努力和所花費的時間)在第一條評論中提到,我的方法均未返回obj4時,我發現了一個問題,並決定實施完全不同的方法。 現在,我的KeyAndValue類還具有一個int Hash字段,當一個構造函數稱為Hash字段時,將key.GetHashCode() ^ tag.GetHashCode()
填充。 它簡化了比較,因為現在我首先將list1與list2組合在一起,然后通過以下方式發送它: CombinedList.GroupBy(x => x.Hash).Select(y => y.First()).ToList();
結果似乎是正確的:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.