Comparing 2 Dictionary<string, string> Instances
I want to compare the contents of two Dictionary<string, string>
instances regardless of the order of the items they contain. SequenceEquals
also compares the order, so I first order the dictionaries by key and then call SequenceEquals
.
Is there a method that I can use instead of SequenceEquals
that will only compare the contents?
If there isn't, is this the ideal way to do this?
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));
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;
}
I don't know if there is an existing method but you could use the following (null checking of args omitted for brevity)
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;
}
It would be best to add an overload to allow customization of the EqualityComparer<TValue>
.
If you use a SortedDictionary you won't need to apply the sorting yourself, which can be slightly easier to use:
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!");
}
}
This will check if all Values
from source
exists in target
, ignoring the Keys
var result = source.All(x => target.Any(y => x.Value == y.Value));
精彩评论