可以订购toLowerCase并规范化问题吗?

时间:2018-03-31 15:15:32

标签: unicode unicode-normalization

我想忽略字符串之间的案例差异和构成差异,所以我有

function normalize(text) {
    return text.normalize("NFD").toLowerCase();
}

它在Javascript中,但原则上不应该是重要的,问题是关于Unicode。

鉴于

function normalize1(text) {
    return text.toLowerCase().normalize("NFD");
}

text1还是text2normalize会在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} 首先是不同的?如果没有,那么主要问题的答案也很清楚"没有"。

1 个答案:

答案 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和其他情况转换不同)的例子。所以在实践中你可能对你问题中的两个函数都很好。