--- +简介
我有两个深的,可能是圆形的Perl数据结构G和E - ref到数组,其元素是散列为哈希或其他数组或标量或...
如何比较它们,并确定E是否是"子集" G?
按子集,我的意思是:
即。数组元素必须完全匹配,但E中的哈希必须是G中哈希的子集。
--- + DETAIL
我很感动通过测试来问这个 - 因此上面例子中的名字G和E,提示"得到"和"期待"。
我经常从编写完全深入比较的测试开始,例如Data :: Compare(或Data :: Dumper序列化的字符串比较)。但是,当您向对象或类(Perl包)添加新字段等时,此类测试很脆弱。或者,当您希望将这些测试不仅应用于特定类的对象,而且应用于从原始类继承但添加其自身功能的对象。
当我厌倦了修复确切的测试时,我将它们转换为不精确的测试。有时通过为应该始终存在的部件创建许多单独的Test :: asserts,这允许其他部件存在而不会破坏测试。或者通过以下几种方式进行字符串化,然后对字符串进行区分 - 我最喜欢的技术之一是使用“路径”打印每个标量项目,使用普通的旧线路方向差异,然后查看差异以确保差异仅在一个方向上。
这很有效,但是有点痛苦,主要是想出一条不错的路径'任何数据结构的表示法。
我相信有更好的方法;我可以想象有更好的方法;我怀疑Perl和CPAN世界已经存在更好的方式;但我的google-fu不足以找到它。
Data :: Compare似乎只对精确比较有用。
数据::匹配和测试::深度似乎非常强大,但没有大量的研究,我看不出如何做到这一点"子集"比较。很可能我的问题的答案只是解释如何将一个特殊的比较函数传递给Test :: Deep的方法之一,这可以做我特殊的"子集"处理任何哈希。
或者可能最好的方法是不使用Data :: Compare,Data :: Match或者Test :: Deep,但只有两个访问者合作遍历这两个对象,能够跳过key = > G中但不是E的值,否则递归。
在这种情况下,我要求指向数据结构遍历/访问者包,这已经解决了圆形对象的问题。 (更糟糕的是,G和E之间的交叉链接 - 尽管我很乐意禁止这样做,但仍然需要处理它们。)
我想我试图让我的思绪围绕Data :: Compare,Data :: Match或Test :: Deep的能力 - 它们是否足以完成深度递归数据结构,或者我应该自己动手?
-
顺便说一下:虽然我定义了"子集"如上所述 - 哈希的子集,数组的完全匹配 - Test :: Deep让我想到了包(无序数组)。但是,我很少在我的代码中使用包,通常使用哈希,其中包的元素是键。更常见的是,我使用可能被称为有序元组的东西,一个有序的哈希:[key1 => value1,key2 => value2,...] - 我把它当作哈希,但是键的顺序很重要。 (想想XML。)
如果有人知道Perl中的标准习语,我很高兴听到它。
我认为哈希和数组的数据结构的深度,精确和子集比较几乎是在存在扩展时通过添加字段进行此类数据结构比较的完整库。特别是如果袋子和我的订购哈希'参与其中。
哦,并且还有适当的结构而不是价值比较 - 确保E中的几个地方指向的子图,而不是简单地在E中深度克隆,依此类推。在处理可重入数据结构时,正确处理这类问题是我更喜欢使用existig库而不是自己编写库的原因之一。
Storabe等序列化库必须解决所有这些遍历问题,所以如果我能找出识别节点上下文的通用方法,那么可以将作为数组元素的节点与其中的节点区分开来。哈希,而不必编写自定义代码,这可能是最好的。广告自动提供调试信息。