c# - 如何在两个 Dictionary<string, List<string>> 对象之间进行值比较

标签 c# unit-testing

我有以下数据结构:

Dictionary<string, List<string>>

我如何进行比较以确保两个不同对象之间的值相等?

即:

    Dictionary<string, List<string>> expected = new Dictionary<string, List<string>>();
    expected.Add("CREDIT", new List<string> { "K   R   EH   D   IH   T" });
    expected.Add("CARD", new List<string> { "K   AA   R   D" });

    Dictionary<string, List<string>> actual;
    actual = target.GetTermDictionary();
    if (!Enumerable.SequenceEqual(expected, actual))
    {
        Assert.Fail();
    }

我不认为 SequanceEqual 在这里很好..

谢谢

最佳答案

快速判断真假的第一个捷径:

if(ReferenceEqual(actual, expected))
  return true;
if(actual == null || expected == null || actual.Count != expected.Count)
  return false;

这也处理空值检查,所以我们做的任何其他事情都不会抛出空引用异常。如果像示例中那样在创建之后就拥有它,则可以跳过所有比较计数的栏,但如果将其放在单独的方法中,则应保留它,以防万一。

我们不能只对两个字典调用 SequenceEqual,因为我们不能保证以相同的顺序取回键。对于其他类型的值,我们可以这样做:

return actual.OrderBy(kvp => kvp.Key).SequenceEqual(expected.OrderBy(kvp => kvp.Key));

但这行不通,因为两个序列相等 List<string>值不会被视为等于 DefaultEqualityComparer<List<string>>.Equals()这将调用的方法。

我们可以创建一个 IEqualityComparer<KeyValuePair<string, List<string>>>如果我们对使用 SequenceEqual 束手无策,但使用非 Linq 方法可能更简单,即使 Linq 通常更简单、更简洁(一旦你找到了这样做的方法。因此:

List<string> expectedVal;
foreach(KeyValuePair<string, List<string> kvp in actual)
{
  if(!expected.TryGetValue(kvp.key, out expectedVal) || kvp.Value.Count != expectedVal.Count || !kvp.Value.SequenceEquals(expectedVal))
    return false;

}
return true;

变体可以处理不同的平等观点。例如,我们可以使用 kvp.Value.OrderBy(x => x).SequenceEquals(expectedVal.OrderBy(x => x))如果我们想将不同顺序的相同项目的两个列表视为相等。

总而言之,很多在一起:

if(ReferenceEqual(actual, expected))
  return true;
if(actual == null || expected == null || actual.Count != expected.Count)
  return false;
List<string> expectedVal;
foreach(KeyValuePair<string, List<string> kvp in actual)
{
  if(!expected.TryGetValue(kvp.key, out expectedVal) || kvp.Value.Count != expectedVal.Count || !kvp.Value.SequenceEquals(expectedVal))
    return false;

}
return true;

编辑:只是为了好玩,使用 SequenceEquals 的方式:

internal class KvpSLSEq : IEqualityComparer<KeyValuePair<string, List<string>>>
{
  public bool Equals(KeyValuePair<string, List<string>> x, KeyValuePair<string, List<string>> y)
  {
    return x.Key == y.Key && x.Value.Count == y.Value.Count && x.Value.SequenceEquals(y.Value);
  }
  public int GetHashCode(KeyValuePair<string, List<string>> obj)
  {
    //you could just throw NotImplementedException unless you'll reuse this elsewhere.
    int hash = obj.Key.GetHashCode;
    foreach(string val in obj.Value)
       hash = hash * 31 + (val == null ? 0 : val.GetHashCode());
  }
}

完成后我们可以使用简洁的:

actual.OrderBy(kvp => kvp.Key).SequenceEqual(expected.OrderBy(kvp => kvp.Key), new KvpSLSEq());

但只有在其他地方也使用 KvpSLSEq 时,它才真正简洁。

关于c# - 如何在两个 Dictionary<string, List<string>> 对象之间进行值比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8502266/

相关文章:

c# - 如何在 C# 中找出 XML 中特定元素之前的元素?

c# - 在 lambda 表达式中的另一个对象列表中获取一个对象列表

java - 如果单例类本身正在使用 PowerMock 进行测试,如何模拟该类的私有(private)方法?

c# - 单元测试需要更多时间做减法

c# - Unity 2D Tilemap 自定义六角规则瓦片

c# - 使用 C# 和 Npgsql 快速插入父表和子表

c# - 在循环中获取每第 100 个值

java - 使用 Arquillian 集成测试遗留 Java EE 应用程序

unit-testing - Zend Framework 2 使用 CodeCeption 进行单元测试

java - 模拟redis模板