我想忽略字符串之间的案例差异和构成差异,所以我有
function normalize(text) {
return text.normalize("NFD").toLowerCase();
}
它在Javascript中,但原则上不应该是重要的,问题是关于Unicode。
鉴于
function normalize1(text) {
return text.toLowerCase().normalize("NFD");
}
是text1
还是text2
,normalize
会在normalize1
上返回相同的结果,但normalize(text)
不会,反之亦然?如果答案是"是",则是这些标准化之一"更正确"在某种意义上?
场景是我的程序维护一个短语列表,并需要确定给定的网页是否包含其中任何一个。最好是假阴性而不是假阳性,因为短语可以很容易地添加(这就是为什么我没有使用NFKD分解)。
次要问题:normalize1(text)
和
iex(2)> list = Enum.to_list 1..1_000_000; :timer.tc(fn -> Enum.sum list end)
{24497, 500000500000}
首先是不同的?如果没有,那么主要问题的答案也很清楚"没有"。
答案 0 :(得分:3)
您应该使用默认无壳匹配算法之一,该算法使用大小写折叠而不是大小写映射。例如,请参阅定义规范无壳匹配的Unicode standard中的以下引用,并部分回答您的问题(强调我的):
原则上,规范化需要在大小写折叠后进行,因为大小写折叠不会在所有实例中保留字符串的规范化形式。规范化的这种要求包含在规范无标记匹配的以下定义中:
D145字符串X是字符串Y的规范无壳匹配,当且仅当:
NFD(toCasefold(NFD(X)))= NFD(toCasefold(NFD(Y)))在D145案例折叠之前,规范分解(NFD归一化)的调用是为了捕捉非常罕见的边缘情况。除了字符U + 0345之外,在案例折叠之前不需要标准化 结合希腊语ypogegrammeni和任何将其作为规范分解的一部分的字符,例如U +1FC3ῃ希腊小字母eta与ypogegrammeni。在实践中,规范无壳匹配的优化版本可以捕获这些特殊情况,从而避免每次比较的额外标准化步骤。
但是如果你正在使用Javascript,你可能会遇到案例映射。如上所述,您应该始终在大小写转换后进行标准化,但我不确定在小写时是否需要边缘情况的预标准化步骤。如果你想保持安全,你甚至可以考虑:
function normalize(text) {
return text.normalize("NFD").toLowerCase().normalize("NFD");
}
那就是说,我无法想出一个NFD归一化和小写的顺序(NFC和其他情况转换不同)的例子。所以在实践中你可能对你问题中的两个函数都很好。