localeCompare在使用前导变音字符排序单词时显示不一致的行为

时间:2015-03-10 14:33:52

标签: javascript arrays sorting

在最新的Firefox和Chrome中测试过(我的系统上有'de'语言环境):

"Ä".localeCompare("A")

给我1,这意味着它认为"Ä"应该按照排序顺序在 "A"之后出现,这是正确的。

可是:

"Ägypten".localeCompare("Algerien")

给我-1,这意味着它认为"Ägypten"应该按照排序顺序在 "Algerien"之前出现

为什么呢?为什么它看起来超过了每个字符串的第一个字符,如果它说第一个字符串的第一个字符应该出现在第二个字符串的第一个字符后,当你自己检查它时呢?

2 个答案:

答案 0 :(得分:1)

http://en.wikipedia.org/wiki/Diaeresis_(diacritic)#Printing_conventions_in_German

  

“按字母顺序对德语单词进行排序时,变音符号通常与底层元音区别开来,但如果两个单词的区别只有变音符号,那么这个单词就会变成第二个[...]   “有一个限制使用的第二个系统,主要用于排序名称(通俗地称为”电话目录排序“),它将ü视为ue,依此类推。”

假设应用了第二种排序算法,那么您看到的结果是有意义的。

Ä将变为Ae,并且比您的其他值A“更长”,因此在A之前排序Ae及其{{1}在A之前是正确的(正如你自己说的那样,你认为这是正确的;即使是第一个将Ä视为Ä的算法,它也是正确的,太)。

现在A变为Ägypten用于排序目的,因此它必须在Aegypten之前出现在相同的排序逻辑中 - 两个术语的第一个字母相等,所以它是向上的确定排序顺序的第二个,Algerien的排序值低于e。因此,在l之前Aegypten,在Algerien之前意味着Ägypten


德国维基百科详细阐述了这一点(http://de.wikipedia.org/wiki/Alphabetische_Sortierung#Einsortierungsregeln_f.C3.BCr_weitere_Buchstaben),并指出相关DIN 5007有两种变体。

DIN 5007变体1说,Algerien被视为äa被视为öo被视为ü,并且这种排序用于字典等。

DIN 5007变体1说明另一件事,u被视为ä等,这主要用于电话簿等名单。

维基百科继续说,这考虑到个人姓名可能有不止一种形式的拼写(某人的姓可能是 Moeller Möller,两个版本都存在),而对于字典中的单词,通常只有一个拼写被认为是正确的。


现在,我想剩下的价格问题是:我可以让浏览器对德语区域设置应用其他形式的排序吗?坦率地说,我不知道。

可能肯定希望能够在这两种形式的排序中进行选择,因为维基百科说个人名称​​ Moeller Möller存在,但只有当涉及字典时,Ägypten而不是 Aegypten

答案 1 :(得分:1)

这里有方法可以满足您的需求,复制粘贴此方法:

递归解析字符串并给出char语言环境比较结果而不是字符串:)

最终结果 错误已修复,为整个字符串添加了比较(不正确的停止或递归循环):

String.prototype.MylocaleCompare = function (right, idx){
    idx = (idx == undefined) ? 0 : idx++;

    var run = right.length <= this.length ? (idx < right.length - 1 ? true : false) : (idx < this.length - 1 ? true : false);


    if (!run) 
    {
        if (this[0].localeCompare(right[0]) == 0)
            {
                return this.localeCompare(right);
            }
            else
            {
                return this[0].localeCompare(right[0])
            }
    }

    if(this.localeCompare(right) != this[0].localeCompare(right[0]))
    {
        var myLeft = this.slice(1, this.length);
        var myRight = right.slice(1, right.length);
        if (myLeft.localeCompare(myRight) != myLeft[0].localeCompare(myRight[0]))
        {
            return myLeft.MylocaleCompare(myRight, idx);
        }
        else
        {
            if (this[0].localeCompare(right[0]) == 0)
            {
                return myLeft.MylocaleCompare(myRight, idx);
            }
            else
            {
                return this[0].localeCompare(right[0])
            }
        }
    }
    else
    {
        return this.localeCompare(right);
    }

}