2012-09-26 29 views
2

根据我的研究和谷歌搜索,JavaScript似乎缺乏支持区域意识排序和字符串比较。有localeCompare(),但它已reported of browser specific differencies和不可能明确设置使用哪个区域设置(OS区域设置并不总是需要的)。有一些intentions to add collation support inside ECMAScript,但在它之前,我们是在我们自己的。并取决于浏览器的结果如何一致,可能是我们永远在我们自己:(准备排序封闭

我有以下的代码,这使得按字母顺序排序的数组。它的速度记住,并得到了想法从https://stackoverflow.com/a/11598969/1691517,我做了一些速度的改进

在这个例子中,单词数组有13个成员和排序函数被称为34次我想要替换单词中的一些字母数组(你因为这不是问题中的要点)如果我在分类函数(以return function(a, b)开头的那个)中进行这些替换,代码是效率低下的,因为替换的次数多于每个阵列成员一次,当然我可以做到这一点在此封闭之外进行替换,我的意思是在行words.sort(sortbyalphabet_timo);之前,但它不是我想要的。

问题1:是否可以修改行“准备开始”和“准备结束”之间的单词数组,以便排序功能使用修改后的单词数组?

问题2:是否可以向闭包输入参数,以便准备开始和准备完成之间的代码可以使用它们?我曾经尝试这样做没有成功:

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

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

var sortbyalphabet_timo = (function() { 
    // PREPARATION STARTS 
    var i, alphabet = "-AaÀàÁáÂâÃãÄä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());` 
+0

你有一个非常有趣的字母表。 – jbabey

+0

是吗?该功能是由用户可以添加他/她想要的任何字母组成的。这只是一个可能的字符顺序的例子。请使用你想要的。 –

回答

2

是否有可能修改的话阵在“准备开始”和“准备结束”这两行之间,以便排序功能使用修改过的单词数组?

不,不是真的。您无权访问数组本身,您的函数仅构建稍后在阵列上调用.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; 
} 

是否有可能输入参数关闭,以便处理开始和准备两端之间的代码可以使用它们?

是的,当然 - 这就是使用闭包的原因:-)但是,您不能在当前的代码中使用​​。立即调用你所关闭的闭包(称为IIFE)并返回比较函数,并将其传递到您的演示中。

如果你想让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); 

...刚刚缓存的结果执行闭包,如果你需要多次排序。

+0

谢谢!为什么您的非关闭建议与关闭版本相比如此缓慢? Closure-version大约是25(或198的Safari)时间更快:http://jsperf.com/collat​​ion-string-sorting/12 –

+0

嗯,你没有通过比较函数,但关闭到'sort() '。我认为,从http://jsperf.com/collat​​ion-string-sorting/14来看,它应该很明显为什么一个人(更快一点)。 – Bergi

+0

这个答案已经值得+1了,因为在这里我们来回答我的问题背后的真相。我问“是否可能”,但真正的意思是“我该如何实现”。我怎么能得到所有这些:封闭版本的速度(所以不需要做多次,如果不需要),使用参数来选择例如。在排序之前不敏感并修改单词数组?我需要不可能的东西吗? –