在以对象为值的字典上使用 Except
Using Except on Dictionaries with Object as Value
直到现在我有 2 部 Dictionary<string, int>
类型的词典,需要使用 except
获取 dict1
中但不在 dict2
中的所有内容。示例:
Dictionary<string, int> dict1 = new Dictionary<string, int>
{
{ "aaa", 1 },
{ "bbb", 2 }
};
Dictionary<string, int> dict2 = new Dictionary<string, int>
{
{ "aaa", 2 },
{ "bbb", 2 }
};
var newDict = dict1.Except(dict2);
newDict
现在包含 { "aaa", 1 } 这是我所期望的,因为值不同。
我的问题是,我们需要字典中的附加值,所以我们将 Dictionary<string, int>
更改为 Dictionary<string, MyObject>
。当我现在使用 except
时,我没有得到我想要的结果。示例:
public class MyObject
{
public MyObject(string name, int someNumber)
{
myString = name;
myInt = someNumber;
}
public string myString { get; set; }
public int myInt { get; set; }
}
class Program
{
static void Main(string[] args)
{
Dictionary<string, MyObject> dict1 = new Dictionary<string, MyObject>
{
{ "aaa", new MyObject("abc", 1) },
{ "bbb", new MyObject("def", 2) }
};
Dictionary<string, MyObject> dict2 = new Dictionary<string, MyObject>
{
{ "aaa", new MyObject("abc", 2) },
{ "bbb", new MyObject("def", 2) }
};
var newDict = dict1.Except(dict2);
}
}
newDict
现在包含来自 dict1 的所有 kvp,但实际上我只想拥有来自 dict1 的第一个条目。我认为这是因为没有比较 MyObject 的值。我能做些什么来解决这个问题?是否有通过 Linq 的简单方法?
提前致谢!
您需要为您的 MyObject
class 实施 GetHashCode()
和 Equals
或为 KeyValuePair<string,MyObject>
:[=17= 使用自定义相等比较器]
public class MyObjectComparer : IEqualityComparer<KeyValuePair<string,MyObject>>
{
public bool Equals(KeyValuePair<string, MyObject> obj1, KeyValuePair<string, MyObject> obj2)
{
if (obj1 == null) return obj2 == null;
if (obj2 == null) return false;
if (obj1.Key != obj2.Key) return false;
if (obj1.Value == null) return obj2.Value == null;
if (obj2.Value == null) return false;
return obj1.Value.myInt == obj2.Value.myInt &&
obj1.Value.myString == obj2.Value.myString;
}
public int GetHashCode(MyObject obj)
{
if (obj == null) return 0;
int hash = obj.Key.GetHashCode();
if (obj.Value == null) return hash;
return hash ^ obj.Value.myInt.GetHashCode() ^ obj.Value.myString.GetHashCode();
}
}
现在将此比较器传递给 Except()
:
var newDict = dict1.Except(dict2, new MyObjectComparer());
您需要在 MyObject
中实施 object.Equals(object other)
。
根据您如何定义对象之间的相等性,它可能如下所示:
public override bool Equals(object other)
{
if(!(other is MyObject))
{
return false;
}
var o = other as MyObject;
return myString.Equals(o.myString) && myInt == o.myInt;
}
正如 René 在评论中所说,在实施 Equals
时同时实施 GetHashCode
通常是个好主意。
直到现在我有 2 部 Dictionary<string, int>
类型的词典,需要使用 except
获取 dict1
中但不在 dict2
中的所有内容。示例:
Dictionary<string, int> dict1 = new Dictionary<string, int>
{
{ "aaa", 1 },
{ "bbb", 2 }
};
Dictionary<string, int> dict2 = new Dictionary<string, int>
{
{ "aaa", 2 },
{ "bbb", 2 }
};
var newDict = dict1.Except(dict2);
newDict
现在包含 { "aaa", 1 } 这是我所期望的,因为值不同。
我的问题是,我们需要字典中的附加值,所以我们将 Dictionary<string, int>
更改为 Dictionary<string, MyObject>
。当我现在使用 except
时,我没有得到我想要的结果。示例:
public class MyObject
{
public MyObject(string name, int someNumber)
{
myString = name;
myInt = someNumber;
}
public string myString { get; set; }
public int myInt { get; set; }
}
class Program
{
static void Main(string[] args)
{
Dictionary<string, MyObject> dict1 = new Dictionary<string, MyObject>
{
{ "aaa", new MyObject("abc", 1) },
{ "bbb", new MyObject("def", 2) }
};
Dictionary<string, MyObject> dict2 = new Dictionary<string, MyObject>
{
{ "aaa", new MyObject("abc", 2) },
{ "bbb", new MyObject("def", 2) }
};
var newDict = dict1.Except(dict2);
}
}
newDict
现在包含来自 dict1 的所有 kvp,但实际上我只想拥有来自 dict1 的第一个条目。我认为这是因为没有比较 MyObject 的值。我能做些什么来解决这个问题?是否有通过 Linq 的简单方法?
提前致谢!
您需要为您的 MyObject
class 实施 GetHashCode()
和 Equals
或为 KeyValuePair<string,MyObject>
:[=17= 使用自定义相等比较器]
public class MyObjectComparer : IEqualityComparer<KeyValuePair<string,MyObject>>
{
public bool Equals(KeyValuePair<string, MyObject> obj1, KeyValuePair<string, MyObject> obj2)
{
if (obj1 == null) return obj2 == null;
if (obj2 == null) return false;
if (obj1.Key != obj2.Key) return false;
if (obj1.Value == null) return obj2.Value == null;
if (obj2.Value == null) return false;
return obj1.Value.myInt == obj2.Value.myInt &&
obj1.Value.myString == obj2.Value.myString;
}
public int GetHashCode(MyObject obj)
{
if (obj == null) return 0;
int hash = obj.Key.GetHashCode();
if (obj.Value == null) return hash;
return hash ^ obj.Value.myInt.GetHashCode() ^ obj.Value.myString.GetHashCode();
}
}
现在将此比较器传递给 Except()
:
var newDict = dict1.Except(dict2, new MyObjectComparer());
您需要在 MyObject
中实施 object.Equals(object other)
。
根据您如何定义对象之间的相等性,它可能如下所示:
public override bool Equals(object other)
{
if(!(other is MyObject))
{
return false;
}
var o = other as MyObject;
return myString.Equals(o.myString) && myInt == o.myInt;
}
正如 René 在评论中所说,在实施 Equals
时同时实施 GetHashCode
通常是个好主意。