Я хочу сравнить в двух словарях С# с ключами a string
и как значение список int
s. Я предполагаю, что два словаря равны, если оба они имеют одинаковые ключи, а для каждого ключа - значение с одним и тем же целым числом (оба необязательно в одном порядке).
Я использую оба ответа из этого и этого связанного с этим вопроса, но оба отказали в моем тестовом наборе для тестовые функции DoesOrderKeysMatter
и DoesOrderValuesMatter
.
Моя тестовая версия:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;
namespace UnitTestProject1
{
[TestClass]
public class ProvideReportTests
{
[TestMethod]
public void AreSameDictionariesEqual()
{
// arrange
Dictionary<string, List<int>> dict1 = new Dictionary<string, List<int>>();
List<int> list1 = new List<int>();
list1.Add(1);
list1.Add(2);
dict1.Add("a", list1);
List<int> list2 = new List<int>();
list2.Add(3);
list2.Add(4);
dict1.Add("b", list2);
// act
bool dictsAreEqual = false;
dictsAreEqual = AreDictionariesEqual(dict1, dict1);
// assert
Assert.IsTrue(dictsAreEqual, "Dictionaries are not equal");
}
[TestMethod]
public void AreDifferentDictionariesNotEqual()
{
// arrange
Dictionary<string, List<int>> dict1 = new Dictionary<string, List<int>>();
List<int> list1 = new List<int>();
list1.Add(1);
list1.Add(2);
dict1.Add("a", list1);
List<int> list2 = new List<int>();
list2.Add(3);
list2.Add(4);
dict1.Add("b", list2);
Dictionary<string, List<int>> dict2 = new Dictionary<string, List<int>>();
// act
bool dictsAreEqual = true;
dictsAreEqual = AreDictionariesEqual(dict1, dict2);
// assert
Assert.IsFalse(dictsAreEqual, "Dictionaries are equal");
}
[TestMethod]
public void DoesOrderKeysMatter()
{
// arrange
Dictionary<string, List<int>> dict1 = new Dictionary<string, List<int>>();
List<int> list1 = new List<int>();
list1.Add(1);
list1.Add(2);
dict1.Add("a", list1);
List<int> list2 = new List<int>();
list2.Add(3);
list2.Add(4);
dict1.Add("b", list2);
Dictionary<string, List<int>> dict2 = new Dictionary<string, List<int>>();
List<int> list3 = new List<int>();
list3.Add(3);
list3.Add(4);
dict2.Add("b", list3);
List<int> list4 = new List<int>();
list4.Add(1);
list4.Add(2);
dict2.Add("a", list4);
// act
bool dictsAreEqual = false;
dictsAreEqual = AreDictionariesEqual(dict1, dict2);
// assert
Assert.IsTrue(dictsAreEqual, "Dictionaries are not equal");
}
[TestMethod]
public void DoesOrderValuesMatter()
{
// arrange
Dictionary<string, List<int>> dict1 = new Dictionary<string, List<int>>();
List<int> list1 = new List<int>();
list1.Add(1);
list1.Add(2);
dict1.Add("a", list1);
List<int> list2 = new List<int>();
list2.Add(3);
list2.Add(4);
dict1.Add("b", list2);
Dictionary<string, List<int>> dict2 = new Dictionary<string, List<int>>();
List<int> list3 = new List<int>();
list3.Add(2);
list3.Add(1);
dict2.Add("a", list3);
List<int> list4 = new List<int>();
list4.Add(4);
list4.Add(3);
dict2.Add("b", list4);
// act
bool dictsAreEqual = false;
dictsAreEqual = AreDictionariesEqual(dict1, dict2);
// assert
Assert.IsTrue(dictsAreEqual, "Dictionaries are not equal");
}
private bool AreDictionariesEqual(Dictionary<string, List<int>> dict1, Dictionary<string, List<int>> dict2)
{
return dict1.Keys.Count == dict2.Keys.Count &&
dict1.Keys.All(k => dict2.ContainsKey(k) && object.Equals(dict2[k], dict1[k]));
// also fails:
// return dict1.OrderBy(kvp => kvp.Key).SequenceEqual(dict2.OrderBy(kvp => kvp.Key));
}
}
}
Каков правильный способ сравнения этих словарей? Или есть ошибка в моем (по общему признанию неуклюже написанном) TestSuite?
Обновление
Я пытаюсь включить ответ Servy в свой тестовый пакет, как показано ниже, но я получаю некоторые ошибки (подчеркнутые красной вигглой в Visual Studio):
-
SetEquals
в `Equals method says:" не содержит определения для SetEquals, принимающего первый аргумент типа Generic.List. -
В AreDictionariesEqual
it says
DictionaryComparer > является типом, но используется как переменная.пространство имен UnitTestProject1 { [TestClass] публичный класс ProvideReportTests { [Метод испытания] //... так же, как указано выше
private bool AreDictionariesEqual(Dictionary<string, List<int>> dict1, Dictionary<string, List<int>> dict2) { DictionaryComparer<string, List<int>>(new ListComparer<int>() dc = new DictionaryComparer<string, List<int>>(new ListComparer<int>(); return dc.Equals(dict1, dict2); } } public class DictionaryComparer<TKey, TValue> : IEqualityComparer<Dictionary<TKey, TValue>> { private IEqualityComparer<TValue> valueComparer; public DictionaryComparer(IEqualityComparer<TValue> valueComparer = null) { this.valueComparer = valueComparer ?? EqualityComparer<TValue>.Default; } public bool Equals(Dictionary<TKey, TValue> x, Dictionary<TKey, TValue> y) { if (x.Count != y.Count) return false; if (x.Keys.Except(y.Keys).Any()) return false; if (y.Keys.Except(x.Keys).Any()) return false; foreach (var pair in x) if (!valueComparer.Equals(pair.Value, y[pair.Key])) return false; return true; } public int GetHashCode(Dictionary<TKey, TValue> obj) { throw new NotImplementedException(); } } public class ListComparer<T> : IEqualityComparer<List<T>> { private IEqualityComparer<T> valueComparer; public ListComparer(IEqualityComparer<T> valueComparer = null) { this.valueComparer = valueComparer ?? EqualityComparer<T>.Default; } public bool Equals(List<T> x, List<T> y) { return x.SetEquals(y, valueComparer); } public int GetHashCode(List<T> obj) { throw new NotImplementedException(); } } public static bool SetEquals<T>(this IEnumerable<T> first, IEnumerable<T> second, IEqualityComparer<T> comparer) { return new HashSet<T>(second, comparer ?? EqualityComparer<T>.Default) .SetEquals(first); }
}