所以我有两个对象列表,对象有多个字段,但我想根据它们中的两个来区分它们。
为了给你提供图片,对象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 as 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,我不知道这是我的自定义比较器的错,我使用它的方式或者我应该使用另一种方法。我一直在查看其他问题,但找不到合适的答案(或者至少有一个我真正知道如何正确实施的答案)。
答案 0 :(得分:0)
我认为你不需要Except
。你想拥有两者的不同价值吗?
var distinctValues = list1.Union(list2).Distinct();
您需要在GetHashCode
中实施Equals
/ KeyAndValue
或使用比较器按键和值比较对象。
(老东西吼叫)
不确定我是否正确理解了这个问题。可能是你没有认识到除了创建一个新的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();
}
}
最后但并非最不重要:当您需要表现时,请考虑使用字典。
答案 1 :(得分:0)
正如Stefan Steinegger(我感谢他们花费的精力和时间)在第一篇评论中提到的,我的方法都没有返回obj4,我发现了一个问题,并决定采用完全不同的方法。现在我的KeyAndValue类还有一个int Hash字段,当一个构造函数被调用时,Hash字段填充了key.GetHashCode() ^ tag.GetHashCode()
。它简化了比较,因为我现在首先将list1与list2合并,然后通过它发送:CombinedList.GroupBy(x => x.Hash).Select(y => y.First()).ToList();
结果似乎是正确的:)