Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自定义IEqualityComparer可以比使用.Where()+;更快地从两个列表中获取不同的对象。任何()_C#_List_Object_Distinct_Iequalitycomparer - Fatal编程技术网

C# 自定义IEqualityComparer可以比使用.Where()+;更快地从两个列表中获取不同的对象。任何()

C# 自定义IEqualityComparer可以比使用.Where()+;更快地从两个列表中获取不同的对象。任何(),c#,list,object,distinct,iequalitycomparer,C#,List,Object,Distinct,Iequalitycomparer,所以我有两个对象列表,对象有多个字段,但我只想根据其中两个字段来区分它们 要显示图片,object 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()

所以我有两个对象列表,对象有多个字段,但我只想根据其中两个字段来区分它们

要显示图片,object 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();
正确的结果是:作为obj3的obj1、obj2和obj4与obj1具有相同的键和标记

我试图实现的是加快这个过程,因为对于很多对象来说,这需要花费太长的时间。我发现定制的IEqualityComparer可以在这里提供帮助,所以我基于 看起来是这样的:

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();

不幸的是,它只从列表2中删除重复项。似乎它甚至没有触及列表1,我不知道这是否是我的自定义比较器的错误,我使用它的方式,或者我应该使用另一种方法。我一直在查看其他问题,但找不到有效的答案(或者至少是我知道如何正确实施的答案)。

我认为您不需要
,只需要
。你想两者都有不同的值吗

var distinctValues = list1.Union(list2).Distinct();
您需要在
KeyAndValue
中实现
GetHashCode
/
Equals
,或者使用比较器按键和值比较对象


(下面是老东西)

不确定我是否正确理解了这个问题。除了创建一个新的IEnumerable并列出一个新列表之外,您是否还没有意识到这一点

尝试:

也许还有:

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();
    }
}
类键比较器:IEqualityComparer
{
公共布尔等于(KeyAndValue x,KeyAndValue y)
{
if(ReferenceEquals(x,y))
返回true;
if(ReferenceEquals(x,null)| | ReferenceEquals(y,null))
返回false;
返回x.key==y.key;
}
public int GetHashCode(KeyAndValue KeyAndValue)
{
if(ReferenceEquals(keyAndValue,null))
返回0;
return keyAndValue.key==null?0:keyAndValue.key.GetHashCode();
}
}


最后但并非最不重要:当你需要表现时,考虑使用字典代替.< /P> < P>作为第一次评论中提到的Stefan Steinegger(我感谢Gristy的努力和时间),我的方法都不返回Obj4,我发现了一个问题,决定实施完全不同的方法。现在,我的KeyAndValue类还有一个int散列字段,当一个构造函数被称为Hash字段时,该字段由

key.GetHashCode()^tag.GetHashCode()
填充。它简化了比较,因为现在我首先将list1与list2组合起来,然后通过以下方式发送:
CombinedList.GroupBy(x=>x.Hash)结果似乎是正确的:)

您的两个方法都不会返回
obj4
。您正在寻找
Union
?1:是的,我正在将结果保存到列表中2:您的KeyComparer没有返回具有相同键但不同标记的对象3:我不确定dictionary在这里是否有效,因为我提到KeyAndValue对象包含两个以上的字段,所以我可以创建dictionary该键具有什么数据类型?我的意思是
Dictionary
通过键快速查找对象。键是一个字符串字段,标记是一个带有字符串字段名的标记(另一个类)对象类型的字段。现在回想起来,也许前面的方法一开始就不起作用,因为我比较了返回标记类对象的标记字段,而不是od tag.name.wird。我还是不明白你想要什么。处理哈希代码时要小心。它们不能取代真正的比较。散列只是一种性能改进,以避免在散列已经不同时调用昂贵的
Equals
。然而,相等的散列并不意味着相等的值!相等散列表示必须调用
Equals
。按哈希代码分组看起来很奇怪
GroupBy
还应该能够使用比较器。
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();
    }
}