0

我正在尝试使用值和文本对选择选项进行排序,如下所示。文本可以有特殊字符,需要排序。但是我发现,一些特殊字符出现在字母之后。我首先想要所有特殊字符,然后是 Alphabets 。

c =    [["#test","#test"], ["?test", "?test"], ["test", "test"], ["TEst", "TEst"], ["]test", "]test"]]
    >>> c.sort()
    [["#test", "#test"], ["?test", "?test"], ["TEst", "TEst"], ["]test", "]test"], ["test", "test"]]

问题似乎是 'TEst' 。

另一个简单的例子:

cool = ['#new','?new','[new',']new','NEw','&new','cool','ind']
["#new", "?new", "[new", "]new", "NEw", "&new", "cool", "ind"]
cool.sort()
["#new", "&new", "?new", "NEw", "[new", "]new", "cool", "ind"]
4

2 回答 2

2

您可以将比较函数作为.sort()函数参数传递,例如

c.sort(function(a, b) {
    if (a.charCodeAt(0) <= 49) {
        return -1;
    }

    return a.localeCompare(b);
})

演示:http: //jsfiddle.net/7DUEg/

于 2013-01-06T09:59:09.217 回答
2

问题特别在于ASCII 代码为 91-96 和 123-126的字符,它们是标点符号或特殊字符,但其代码高于字母字符。所以你的排序功能需要考虑到这一点。

例如,您可以通过将这些字符映射到较低的 ASCII 字符来做到这一点。http://jsfiddle.net/LGjnY/4/

function transformString(s) {
  var r = '',
    code;
  for (var i = 0; i < s.length; i++) {
    code = s.charCodeAt(i);
    // map 91-96 onto 22-27
    if (code >= 91 && code <= 96) code -= 69; 
    // map 123-126 onto 28-31
    else if (code >= 123 && code <= 126) code -= 95; 
    r += String.fromCharCode(code);
  }
  return r;
}
c.sort(function (a, b) {
  return transformString(a[0]).localeCompare(transformString(b[0]));
});

或者结合比较和转换以使其更快(jsfiddle;未经过真正测试)

function compareTransformedStrings(a, b) {
    if (a == b) return 0;
    for (var i = 0, A, B; (A = a.charCodeAt(i)) && (B = b.charCodeAt(i)); i++) {
        if (A != B) {
            return A - (A >= 91 && A <= 96) * 69 - (A >= 123 && A <= 126) * 95
                < B - (B >= 91 && B <= 96) * 69 - (B >= 123 && B <= 126) * 95 
                ? -1 : 1;
        }
    }
    return a.length < b.length ? -1 : 1;
}
c.sort(function (a, b) {
    return compareTransformedStrings(a[0], b[0]);
});
于 2013-01-06T10:11:02.227 回答