比较 2 个 Dictionary<string, string> 实例
Posted
技术标签:
【中文标题】比较 2 个 Dictionary<string, string> 实例【英文标题】:Comparing 2 Dictionary<string, string> Instances 【发布时间】:2010-10-13 23:16:01 【问题描述】:我想比较两个Dictionary<string, string>
实例的内容,而不管它们包含的项目的顺序如何。 SequenceEquals
也比较顺序,所以我先按键排序字典,然后调用SequenceEquals
。
有什么方法可以代替SequenceEquals
只比较内容吗?
如果没有,这是理想的方法吗?
Dictionary<string, string> source = new Dictionary<string, string>();
Dictionary<string, string> target = new Dictionary<string, string>();
source["foo"] = "bar";
source["baz"] = "zed";
source["blah"] = null;
target["baz"] = "zed";
target["blah"] = null;
target["foo"] = "bar";
// sequenceEquals will be false
var sequenceEqual = source.SequenceEqual(target);
// contentsEqual will be true
var contentsEqual = source.OrderBy(x => x.Key).SequenceEqual(target.OrderBy(x => x.Key));
【问题讨论】:
这个问题包含一个很大的缺陷。没有元素在字典中的顺序之类的东西。根据定义,字典保存键值对,没有任何隐式排序。 【参考方案1】:var contentsEqual = source.DictionaryEqual(target);
// ...
public static bool DictionaryEqual<TKey, TValue>(
this IDictionary<TKey, TValue> first, IDictionary<TKey, TValue> second)
return first.DictionaryEqual(second, null);
public static bool DictionaryEqual<TKey, TValue>(
this IDictionary<TKey, TValue> first, IDictionary<TKey, TValue> second,
IEqualityComparer<TValue> valueComparer)
if (first == second) return true;
if ((first == null) || (second == null)) return false;
if (first.Count != second.Count) return false;
valueComparer = valueComparer ?? EqualityComparer<TValue>.Default;
foreach (var kvp in first)
TValue secondValue;
if (!second.TryGetValue(kvp.Key, out secondValue)) return false;
if (!valueComparer.Equals(kvp.Value, secondValue)) return false;
return true;
【讨论】:
通过无序字典,您的算法可以在 O(n^2) 中运行。 @Yuriy: O(n^2),假设哈希码是半体面的? 假设 GetHash 已实现。 我承认,我不知道 Object 上的 GetHashCode 实现返回了真实的哈希码。 @Yuriy:如果您使用字典,那么您要么 假设哈希码是一半,或者 你确保它们是.字典中的键查找被假定为大约 O(1)。如果不是,那么您将看到全面的性能不佳,而不仅仅是我的方法。【参考方案2】:我不知道是否存在现有方法,但您可以使用以下方法(为简洁起见,省略了对 args 的空检查)
public static bool DictionaryEquals<TKey,TValue>(
this Dictionary<TKey,TValue> left,
Dictionary<TKey,TValue> right )
var comp = EqualityComparer<TValue>.Default;
if ( left.Count != right.Count )
return false;
foreach ( var pair in left )
TValue value;
if ( !right.TryGetValue(pair.Key, out value)
|| !comp.Equals(pair.Value, value) )
return false;
return true;
最好添加一个重载以允许自定义EqualityComparer<TValue>
。
【讨论】:
【参考方案3】:如果您使用SortedDictionary,则无需自行应用排序,使用起来会稍微容易一些:
void Main()
var d1 = new Dictionary<string, string>
["a"] = "Hi there!",
["b"] = "asd",
["c"] = "def"
;
var d2 = new Dictionary<string, string>
["b"] = "asd",
["a"] = "Hi there!",
["c"] = "def"
;
var sortedDictionary1 = new SortedDictionary<string, string>(d1);
var sortedDictionary2 = new SortedDictionary<string, string>(d2);
if (sortedDictionary1.SequenceEqual(sortedDictionary2))
Console.WriteLine("Match!");
else
Console.WriteLine("Not match!");
【讨论】:
【参考方案4】:这将检查source
中的所有Values
是否存在于target
中,忽略Keys
var result = source.All(x => target.Any(y => x.Value == y.Value));
【讨论】:
这错过了target
具有不在source
中的附加键值对的情况
@JaredPar:如果target
有额外的配对,那么会发生什么?返回false
而不是true
?然后额外检查长度会解决它吗?
我会说如果内容不同,那么它们就不相等。长度检查将解决 target
更大但不是密钥不同的问题。
@JaredPar:我假设 OP 只想比较内容。 [...] that will only compare the contents?
以上是关于比较 2 个 Dictionary<string, string> 实例的主要内容,如果未能解决你的问题,请参考以下文章