5

我正在尝试根据对象的name属性对对象数组进行排序。有些名字以“Æ”开头,我希望它们像“Ae”一样被排序。我目前的解决方案如下:

myArray.sort(function(a, b) {
  var aName = a.name.replace(/Æ/gi, 'Ae'),
      bName = b.name.replace(/Æ/gi, 'Ae');
  return aName.localeCompare(bName);
});

我觉得应该有更好的方法来处理这个问题,而不必手动替换每个特殊字符。这可能吗?

如果有任何区别,我会在 Node.js 中执行此操作。

4

1 回答 1

5

没有更简单的方法。不幸的是,即使问题中描述的方式也太简单了,至少在可移植性有任何问题的情况下。

localeCompare方法根据定义是依赖于实现的,它通常取决于底层操作系统的 UI 语言,尽管它也可能在同一台计算机中的浏览器(或其他 JavaScript 实现)之间有所不同。很难找到关于它的任何文档,因此即使您的目标是编写不可移植的代码,您也可能需要进行大量测试以查看应用了哪种排序规则。参照。对字符串进行排序比您想象的要困难得多!

因此,要进行可控且可移植的比较,您需要自己编写代码,除非您有幸找到恰好适合您需求的其他人的代码。积极的一面是,大小写转换方法是 JavaScript 中为数不多的本地化就绪的部分之一:它们应用 Unicode 大小写映射规则,因此例如'æ'.toUpperCase()在任何实现中都会产生 Æ。

通常,对字符串进行排序需要一个复杂的函数,该函数应用为一种语言或其他一些规则定义的特定排序规则,例如泛欧排序规则(用于多语言内容)。但是,如果我们可以限制自己的排序规则只处理除了 Ascii 之外的少数字母,我们可以使用如下代码简化德语排序(摘自Going Global with JavaScript and Globalize.js一书):

String.prototype.removeUmlauts = function () {
  return this.replace(/Ä/g,'A').replace(/Ö/g,'O').replace(/Ü/g,'U');
}; 
function alphabetic(str1, str2) {
  var a = str1.toUpperCase().removeUmlauts();
  var b = str2.toUpperCase().removeUmlauts();
  return a < b ? -1 : a > b ? 1 : 0;
}

replace(/Æ/gi, 'Ae')在分析可能出现的字符并决定如何处理它们之后,您可以添加其他映射,例如。删除变音符号(例如将 É 映射到 E)很简单,但通常已经足够好了,而且肯定比让实现来决定 É 是否在 Z 之后更好。至少你会在不同的实现中得到一致的结果,你会看到什么出现问题并需要修复,而不是等待其他用户抱怨您的代码排序错误(在他们的环境中)。

于 2012-09-10T04:55:58.053 回答