比较 C 语言中深度嵌套字典的 2 个对象#

Compare 2 objects which are deep nested dictionaries in C#

提问人:axcelenator 提问时间:5/25/2022 最后编辑:Peter Csalaaxcelenator 更新时间:5/25/2022 访问量:363

问:

我有一个很深的嵌套词典:

var a1 = new Dictionary<string, Dictionary<string, Dictionary<string, Person>>>();
var a2 = new Dictionary<string, Dictionary<string, Dictionary<string, Person>>>();

其中是一些包含成员的数据结构,如 , , ...Personnamefamilyage

public class Person
{
    public string name{ get; set; }
    public string family{ get; set; }
    public int age { get; set; }
}

我想比较一下 A1 和 A2,尤其是成员之间。 最好的方法是什么?Person's

C# 字典 相等

评论

0赞 Jeroen Mostert 5/25/2022
定义“最佳”。最方便的方法之一是序列化为 JSON,然后进行比较,尽管这效率低得惊人。一般来说,从嵌套字典转向记录(免费提供值比较语义)之类的东西也可能是一个好主意。
0赞 axcelenator 5/25/2022
实际上,我在单元测试中就是这样做的
1赞 Jeroen Mostert 5/25/2022
许多测试框架确实有方便的结构比较方法(如 Fluent Assertions' )。如果这些方法不支持字典,则使用简单的 LINQ 查询将内容转换为基于列表(有序)的键值对即可。Should().BeEquivalentTo()

答:

1赞 Rafal 5/25/2022 #1

我认为没有开箱即用的解决方案,因为库没有给出对象的深度比较,因为以涵盖大多数用例的通用方式定义它不是一项微不足道的任务。对于您特定的一个,它很容易实现。您只需要编写 2 个比较字典的方法和一个比较对象的方法:

void Compare<T, G>(Dictionary<T, G> first, Dictionary<T, G> second)
{
    foreach (var item in first)
    {
        if (!second.ContainsKey(item.Key)) Assert.Fail();

        var secondValue = second[item.Key];

        Compare(item.Value, secondValue);
    }
}

void Compare<T>(T first, T second)
{
    if (first is Dictionary<string, Dictionary<string, Dictionary<string, Person>>> f)
    {
        Compare(f, (Dictionary<string, Dictionary<string, Dictionary<string, Person>>>)(object)second);
    }
    else if (first is Dictionary<string, Dictionary<string, Person>> f1)
    {
        Compare(f1, (Dictionary<string, Dictionary<string, Person>>)(object)second);
    }
    else if (first is Dictionary<string, Person> f2)
    {
        Compare(f2, (Dictionary<string, Person>)(object)second);
    }
    else
    {
        foreach (var property in typeof(T).GetRuntimeProperties())
        {
            Assert.AreEqual(property.GetValue(first), property.GetValue(second));
        }
    }
}

此代码片段未涵盖很多内容,但您可以对其进行扩展以匹配您的用例。

评论

0赞 axcelenator 5/25/2022
是否有 linq 选项可以将嵌套字典展平为字符串?
0赞 Rafal 5/25/2022
你可以把它展平,假设点连接足够好,不会引入冲突,你可以比较扁平化版本,就好像它是单个字典一样;我认为这不值得first.SelectMany(x=> x.Value.SelectMany(z=> z.Value.SelectMany(y=> ($"{x.key}.{z.key}.{y.key}",y.value)))