我正在测试 UNION 方法以合并到字典(类型为Dictionary)。它适用于TValue类型是字符串或int甚至对象。但是如果TValue类型是一个集合(使用List和object []测试),则抛出异常:“ArgumentException:已经添加了具有相同键的项目。”
这是我的代码:
Dictionary<int,string> _dico1 = new Dictionary<int, string>()
{
{0, "zero"},
{1, "one"}
};
Dictionary<int,string> _dico2 = new Dictionary<int,string>()
{
{1 , "one"},
{2 , "two"},
{3 , "three"},
{4 , "four"},
{5 , "five"},
{6 , "six"}
};
Dictionary<int, List<string>> _dico3 = new Dictionary<int, List<string>>()
{
{0, new List<string>{"zero"}},
{1, new List<string>{"one"}}
};
Dictionary<int, List<string>> _dico4 = new Dictionary<int, List<string>>()
{
{1, new List<string>{"one"}},
{2, new List<string>{"two"}},
{3, new List<string>{"three"}},
{4, new List<string>{"four"}},
{5, new List<string>{"five"}},
{6, new List<string>{"six"}},
};
// works fine
var mergeDico = _dico1.Union(_dico2).ToDictionary(key => key.Key, value => value.Value);
// throw an ArgumentException : An item with the same key has already been added
var mergeDico2 = _dico3.Union(_dico4).ToDictionary(key => key.Key, value => value.Value);
为什么行为不一样?以及如何解决这个问题?
谢谢!
答案 0 :(得分:7)
在第一种情况下,Union正在丢弃重复键,因为键/值对本身是相等的。在第二种情况下,他们不是,因为List<String>{"one"}
不等于另一个List<string>{"one"}
。
我怀疑您希望Union
来电IEqualityComparer
使用{{1}},只会考虑字典中的键。
答案 1 :(得分:2)
您可以使用以下代码合并第二对词典:
var mergeDico2 = _dico3
.Concat(_dico4)
.GroupBy(_=> _.Key, _ => _.Value)
.ToDictionary(
group => group.Key,
group => group.SelectMany(_ => _).ToList());
它将生成一个新字典,其中每个值都是连接两个字典值的列表的结果。如果您只需要列表的不同元素,则可以将ToDictionary调用更改为:
var mergeDico2 = _dico3
.Concat(_dico4)
.GroupBy(_=> _.Key, _ => _.Value)
.ToDictionary(
group => group.Key,
group => group.SelectMany(_ => _).Distinct().ToList());
答案 2 :(得分:1)
正如Jon所说,我们需要实施IEqualityComparer
来解决上述问题。以下是代码如何完成:
的IEqualityComparer:
public class MyEqualityComparer : IEqualityComparer<KeyValuePair<int,List<string>>>
{
public bool Equals(KeyValuePair<int, List<string>> x, KeyValuePair<int, List<string>> y)
{
//Let's say we are comparing the keys only.
return x.Key == y.Key;
}
public int GetHashCode(KeyValuePair<int, List<string>> obj)
{
return obj.Key.GetHashCode();
}
}
用法:
Dictionary<int, List<string>> _dico3 = new Dictionary<int, List<string>>()
{
{0, new List<string> {"zero"}},
{1, new List<string> {"one"}}
};
Dictionary<int, List<string>> _dico4 = new Dictionary<int, List<string>>()
{
{1, new List<string> {"one"}},
{2, new List<string> {"two"}},
{3, new List<string> {"three"}},
{4, new List<string> {"four"}},
{5, new List<string> {"five"}},
{6, new List<string> {"six"}},
};
Dictionary<int, List<string>> mergeDico2 = _dico3.Union(_dico4, new MyEqualityComparer())
.ToDictionary(x => x.Key, x => x.Value);