如何规范化字符串的函数参数列表,以便两个参数列表转换为相同的字符串iff它们实际上是等效的?算法应该
这对于memoization是必要的,即根据其参数缓存函数的结果.
作为一个稻草人的例子,Memoize使用它作为默认的规范化器,它失败了#1和#3:
$argstr = join chr(28),@_;
Run Code Online (Sandbox Code Playgroud)
有一段时间,我的首选标准化程序是
JSON::XS->new->utf8->canonical
Run Code Online (Sandbox Code Playgroud)
然而,它根据最近如何使用标量来区别对待数字3和字符串"3" .这可以为基本等效的参数列表生成不同的字符串,并降低memoization的好处.(绝大多数功能都不知道或不关心他们是3还是"3".)
为了好玩,我查看了一堆序列化程序,看看哪些区分3和"3":
Data::Dump : equal - [3] vs [3]
Data::Dumper : not equal - [3] vs ['3']
FreezeThaw : equal - FrT;@1|@1|$1|3 vs FrT;@1|@1|$1|3
JSON::PP : not equal - [3] vs ["3"]
JSON::XS : not equal - [3] vs ["3"]
Storable : not equal - <unprintable>
YAML : equal - ---\n- 3\n vs ---\n- 3\n
YAML::Syck : equal - --- \n- 3\n vs --- \n- 3\n
YAML::XS : not equal - ---\n- 3\n vs ---\n- '3'\n
Run Code Online (Sandbox Code Playgroud)
报告"相等"的那些,不知道如何让他们忽略哈希键顺序.
我可以预先走参数列表并对所有数字进行字符串化,但这需要制作一份深层副本并违反#5.
谢谢!
几乎任何序列化程序都会以不同的方式对待 3 和“3”,因为它不知道数字和字符串化数字对您来说是相同的,并且这种假设对于一般数据来说是错误的。您必须自己规范化输入或输出。
对于输入,深度扫描并用其值+0替换任何字符串化数字即可。如果您知道输入中数字的确切位置,则可以大大缩短此扫描时间。
对于输出,一些简单的状态机甚至正则表达式(是的,我知道输出不规则)很可能足以将纯数字字符串值剥离为数字。