IE8中的Javascript:如何按字母数字属性对对象数组排序

IE8中的Javascript:如何按字母数字属性对对象数组排序,javascript,sorting,Javascript,Sorting,我有一个Javascript对象数组,我希望通过一个始终是正整数的属性进行交叉兼容排序,该属性的末尾有一个可选的单字母。我正在寻找一个至少能在Firefox3和InternetExplorer8上运行的解决方案。我最接近这种排序函数的是: var arrayOfObjects = [{id: '1A', name: 'bar', size: 'big'}, {id: '1C', name: 'bar', size: 'small'}, {id: '1', name: 'foo', size: '

我有一个Javascript对象数组,我希望通过一个始终是正整数的属性进行交叉兼容排序,该属性的末尾有一个可选的单字母。我正在寻找一个至少能在Firefox3和InternetExplorer8上运行的解决方案。我最接近这种排序函数的是:

var arrayOfObjects = [{id: '1A', name: 'bar', size: 'big'}, {id: '1C', name: 'bar', size: 'small'}, {id: '1', name: 'foo', size: 'big'}, {id: '1F', name: 'bar', size: 'big'}, {id: '1E', name: 'bar', size: 'big'}, {id: '1B', name: 'bar', size: 'small'}, {id: '1D', name: 'bar', size: 'big'}, {id: '1G', name: 'foo', size: 'small'},  {id: '3', name: 'foo', size: 'small'}, {id: '23', name: 'foo', size: 'small'}, {id: '2', name: 'foo', size: 'small'}, {id: '1010', name: 'foo', size: 'small'}, {id: '23C', name: 'foo', size: 'small'}, {id: '15', name: 'foo', size: 'small'}]

arrayOfObjects.sort(function(a, b){
    return (a.id < b.id ? -1 : a.id == b.id ? 0 : 1);
});
var arrayOfObjects=[{id:'1A',name:'bar',size:'big'},{id:'1C',name:'bar',size:'small'},{id:'1',name:'foo',size:'big'},{id:'1F',name:'bar',size:'big'},{id:'1B',size:'small'},{id:'1D',bar',size:'big',name:'foo',size:'small'},{id:'3',name:'foo',size:'small'},{id:'23',name:'foo',size:'small'},{id:'2',name:'foo',size:'small'},{id:'1010',name:'foo',size:'small'},{id:'15',name:'foo',size:'small'}
arrayOfObjects.sort(函数(a,b){
返回值(a.id
经过如此分类后,打印出arrayOfObjects将给出:

1,富,大
1010,富,小
15,foo,small
1A,酒吧,大的
1B,酒吧,小的
1C,条形,小型
1D、条形、大尺寸
1E,酒吧,大的
一层,酒吧,大的
1G,foo,small
2,foo,small
23,foo,small
23C,foo,small
3,小福

但是,我希望arrayOfObjects按以下顺序打印:

1,富,大
1A,酒吧,大的
1B,酒吧,小的
1C,条形,小型
1D、条形、大尺寸
1E,酒吧,大的
一层,酒吧,大的
1G,foo,small
2,foo,small
3,foo,small
15,foo,small
23,foo,small
23C,foo,small
1010,小福

鉴于此,我如何修复上述函数,使对象按数字作为主键,按字母作为辅助键进行排序?提前感谢您的帮助。

arrayOfObjects.sort((函数(){
arrayOfObjects.sort((function() {
  var splitter = /^(\d+)([A-Z]*)/;
  return function(a, b) {
    a = a.id.match(splitter); b = b.id.match(splitter);
    var anum = parseInt(a[1], 10), bnum = parseInt(b[1], 10);
    if (anum === bnum)
      return a[2] < b[2] ? -1 : a[2] > b[2] ? 1 : 0;
    return anum - bnum;
  }
})());
变量拆分器=/^(\d+)([A-Z]*)/; 返回函数(a,b){ a=a.id.match(拆分器);b=b.id.match(拆分器); var-anum=parseInt(a[1],10),bnum=parseInt(b[1],10); 如果(anum==bnum) 返回a[2]b[2]?1:0; 返回anum-bnum; } })());
其思想是将键分为数字部分和字符串部分

编辑(oops获得了向后的“匹配”调用)

再次编辑@Ryan Tenney明智地建议匿名外部函数实际上并不必要:

arrayOfObjects.sort(function(a, b) {
  var splitter = /^(\d+)([A-Z]*)/;
  a = a.id.match(splitter); b = b.id.match(splitter);
  var anum = parseInt(a[1], 10), bnum = parseInt(b[1], 10);
  if (anum === bnum)
    return a[2] < b[2] ? -1 : a[2] > b[2] ? 1 : 0;
  return anum - bnum;     
});
arrayOfObjects.sort(函数(a,b){
变量拆分器=/^(\d+)([A-Z]*)/;
a=a.id.match(拆分器);b=b.id.match(拆分器);
var-anum=parseInt(a[1],10),bnum=parseInt(b[1],10);
如果(anum==bnum)
返回a[2]b[2]?1:0;
返回anum-bnum;
});

简单一点。

您不需要从一串数字中解析整数-

如果两个数字串匹配,则值无关紧要,您可以查看一个可能的字母

如果数字不匹配,则从另一个数字中减去一个将强制生成数字

var rx=/^(\d+)(\D?)$/;

    arrayOfObjects.sort(function(a, b){ 
        var id_a= a.id.match(rx), id_b= b.id.match(rx);
        if(id_a[1]== id_b[1]){
            if(id_a[2]=== id_b[2]) return 0;
            else{
                if(!id_a[2]) return -1;
                if(!id_b[2]) return 1;
                return id_a[2]> id_b[2]? 1: -1;
            }
        }
        return id_a[1]-id_b[1];
    });

下面是compare函数,其中包含更详细的代码和有意义的变量名:

/**
* Sort array ba numerical & alphabetical order ["1a", "2z", "2a", 99, 100]
*/
function compare(a, b) { 

    var re = /(\d+)([^ ]?)/, numA, numB, charA, charB,
        aMatches = re.exec(a),
        bMatches = re.exec(b) ;

    numA = aMatches[1] ? aMatches[1] : ''; //get the number part
    charA = aMatches[2] ? aMatches[2] : ''; //get the char part

    numB = bMatches[1] ? bMatches[1] : '';
    charB = bMatches[2] ? bMatches[2] : '';

    if (charA || charB){ //if one or both of the compare candidates have letter
        if (numA==numB){ //only if number parts are equal
            return charA.localeCompare(charB); // we compare letters 
        }
    }

    return numA - numB; // otherwise just compare numbers
}

正则表达式文字不会给每次迭代增加任何成本。你最好摆脱外部的自执行函数,在内部函数中声明splitter。除此之外,这是一个很好的答案。它比我准备提供的答案要简洁得多:)我有一个关于重复正则表达式的东西-它不太适合性能mance,因为它是关于维护的。也许每一百次尝试中就有一次,我会在第一次尝试时得到一个正确的正则表达式,所以我想尽量减少重复它的次数。当然,我可以在函数体中键入一个
var
,我没有考虑太多。我想你可以将第一次返回改为
returna[2]
并且仍然可以进行排序。@Daniel好吧,这可能会使排序不稳定-一个“稳定”排序是指将已经按顺序排列的元素(由于键相等)保持在相同的顺序,而一个“不稳定”排序排序可以置换它们。我不确定这是真的,但我总是显式地检查键的相等性,这样一个稳定的排序就可以真正保持稳定。