【问题标题】:Prepare array for sorting in closure准备数组以进行闭包排序
【发布时间】:2012-09-18 08:58:10
【问题描述】:

根据我的研究和谷歌搜索,Javascript 似乎缺乏对区域感知排序和字符串比较的支持。有localeCompare(),但一直是reported of browser specific differencies,并且无法显式设置使用哪种语言环境(操作系统语言环境并不总是需要的)。有一些intentions to add collation support inside ECMAScript,但在此之前,我们靠自己。根据不同浏览器结果的一致性,我们可能永远靠自己:(。

我有以下代码,它使数组按字母排序。它考虑了速度,想法来自https://stackoverflow.com/a/11598969/1691517,我对此做了一些速度改进。

在这个例子中,单词数组有 13 个成员,排序函数被调用了 34 次。我想替换 words-array 中的一些字母(你不必知道做了哪些替换,因为这不是这个问题的重点)。如果我在排序函数中进行这些替换(以 return function(a, b) 开头的那个),代码效率低下,因为每个数组成员多次替换。当然我可以在这个闭包之外进行这些替换,我的意思是在words.sort(sortbyalphabet_timo); 行之前,但这不是我想要的。

问题 1: 是否可以修改 "PREPARATION STARTS" 和 "PREPARATION ENDS" 行之间的单词数组,以便排序函数使用修改后的单词数组?

问题 2: 是否可以向闭包输入参数,以便 PREPARATION STARTS 和 PREPARATION ENDS 之间的代码可以使用它们?我试过这个没有成功:

var caseinsensitive = true;
words.sort( sortbyalphabet_timo(caseinsensitive) );

最后是代码示例,准备运行的示例在http://jsfiddle.net/3E7wb/

var sortbyalphabet_timo = (function() {
  // PREPARATION STARTS
  var i, alphabet = "-0123456789AaÀàÁáÂâÃãÄäBbCcÇçDdEeÈèÉéÊêËëFfGgHhIiÌìÍíÎîÏïJjKkLlMmNnÑñOoÒòÓóÔôÕõÖöPpQqRrSsTtUuÙùÚúÛûÜüVvWwXxYyÝýŸÿZz",
  index = {};

  i = alphabet.length;
  while (i--) index[alphabet.charCodeAt(i)] = i;
  // PREPARATION ENDS

  return function(a, b) {
    var i, len, diff;

    if (typeof a === "string" && typeof b === "string") {
      (a.length > b.length) ? len = a.length : len = b.length;
      for (i = 0; i < len; i++) {
        diff = index[a.charCodeAt(i)] - index[b.charCodeAt(i)];

        if (diff !== 0) {
          return diff;
        }
      }
      // sort the shorter first
      return a.length - b.length;
    } else {
      return 0;
    }
  };
})();

var words = ['tauschen', '66', '55', '33', 'täuschen', 'andern', 'ändern', 'Ast', 'Äste', 'dosen', 'dösen', 'Donaudam-0', 'Donaudam-1'];
$('#orig').html(words.toString());
words.sort(sortbyalphabet_timo);
$('#sorted').html(words.toString());`

【问题讨论】:

  • 你的字母表很有趣。
  • 是吗?该功能是由意图制成的,用户可以添加他/她想要的任何字母。这只是一种可能的字符顺序的示例。请使用您想要的。

标签: javascript sorting unicode collation alphabet


【解决方案1】:

是否可以修改 "PREPARATION STARTS" 和 "PREPARATION ENDS" 行之间的单词数组,以便排序函数使用修改后的单词数组?

不,不是真的。您无权访问数组本身,您的函数仅构建稍后在数组上调用 .sort 时使用的比较函数。如果您需要更改数组,则需要编写一个将其作为参数的函数;例如,您可以在Array.prototype 上添加一个方法。它看起来像

function mysort(arr) {
    // Preparation
    // declaration of compare function
    // OR execution of closure to get the compare function
    arr.sort(comparefn);
    return arr;
}

是否可以向闭包输入参数,以便 PREPARATION STARTS 和 PREPARATION ENDS 之间的代码可以使用它们?

是的,当然 - 这就是使用闭包的原因 :-) 但是,您不能在当前代码中使用 sortbyalphabet_timo(caseinsensitive)。您拥有的闭包会立即被调用(称为 IIFE)并返回比较函数,您可以像在演示中那样将其传递给 sort。

如果您希望 sortbyalphabet_timo 成为闭包而不是结果,则必须删除它后面的括号。你也可以在那里使用参数,这些参数可以在整个闭包范围内访问(包括 comparefunction):

var sortbyalphabet_timo_closure = function(caseinsensitive) {
    // Preparation, potentially using the arguments
    // Declaration of compare function, potentially using the arguments
    return comparefn;
}
// then use
words.sort(sortbyalphabet_timo_closure(true));

目前,您正在这样做:

var sortbyalphabet_timo_closure = function(/*having no arguments*/) {
    // Preparation, potentially using the arguments
    // Declaration of compare function, potentially using the arguments
    return comparefn;
}
var sortbyalphabet_timo = sortbyalphabet_timo_closure();
// then use
words.sort(sortbyalphabet_timo);

...如果您需要多次排序,它只会缓存执行闭包的结果。

【讨论】:

  • 谢谢!与闭包版本相比,为什么您的非闭包提案如此缓慢? Closure-version 大约快 25 倍(或 Safari 中的 198 倍):jsperf.com/collation-string-sorting/12
  • 嗯,您没有传递比较函数,而是将闭包传递给sort()。我认为jsperf.com/collation-string-sorting/14 应该很明显为什么一个人(有点)更快。
  • 这个答案值得 +1,因为我们在这里找到了我的问题背后的真相。我问“有没有可能”,但真正的意思是“我怎样才能做到”。我怎样才能得到所有这些:闭包版本的速度(所以如果不需要,什么都不做多次),使用参数来选择,例如。不敏感并在排序之前修改单词数组?我需要一些不可能的东西吗?
  • 是的。使用参数 cached-closure-result 的速度有点矛盾。修改数组与闭包无关。
  • 修改单词数组当然可以在闭包之外完成。如果我们想例如。使排序不敏感,我们可以将数组成员转换为小写或大写,如果我们想让排序重音不敏感,我们可以将所有重音转换为非重音。
猜你喜欢
  • 1970-01-01
  • 2015-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多