2010-09-28 28 views
5

我有一个Javascript对象的数组,我想交叉兼容排序的属性总是一个正整数与一个可选的单个字母在结束。我正在寻找至少工作在溶液中的Firefox 3和Internet Explorer 8,我得出这样一个排序功能最接近的是以下几点:在IE8中的Javascript:如何按字母数字属性排序对象的数组

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); 
}); 

被这样分类后,打印出arrayOfObjects给:

1,FOO,大
1010,FOO,小
15,FOO,小
1A,酒吧,大
1B,栏中,小
1C,酒吧,小
1D,杆,大
1E,酒吧,大
1F,酒吧,大
1G,FOO,小
2,FOO,小
23,FOO,小
23C,FOO,小
3,FOO ,小

不过,我想arrayOfObjects按以下顺序打印出:

1,富,大
1A,酒吧,大
1B ,棒,小
1C,酒吧,小
1D,酒吧,大
1E,酒吧,大
1F,酒吧,大
1G,FOO,小
2,FOO,小
3, FOO,小
15,FOO,小
23,FOO,小
23C,FOO,小
1010,FOO,小

鉴于这种情况,我该如何解决的AB ove函数,使对象按数字排序为主键,字母排序为辅助键?预先感谢您的帮助。

回答

3
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; 
    } 
})()); 

想法是将键分成数字和字符串部分。

编辑(哎呀拿到了“匹配”叫向后)

编辑再次 @Ryan坦尼明智地表明,匿名外的功能是不是真的有必要:

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;  
}); 

一点简单。

+0

正则表达式字面不会将任何成本添加到每个迭代。你最好摆脱外部自我执行功能并在内部函数中声明splitter。 – 2010-09-28 23:51:36

+0

除此之外,很好的答案。它比我准备提供的答案要简洁得多:) – 2010-09-28 23:52:23

+0

我有一件关于重复正则表达式的事情 - 它不是关于性能,而是关于维护。也许一次尝试百次,我会在第一时间得到正确的正则表达式,所以我想尽量减少重复次数。当然,我可以在函数体中将它作为'var'键入;我没有多想这件事。 – Pointy 2010-09-28 23:55:22

0

你并不需要解析整数出来的digits-

字符串如果数字匹配的两个字符串,其值没关系,你看一个可能的字母。

如果数字不匹配,则从其他数字中减去一个数字就会强制数字。

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]; 
    }); 
0

下面是比较功能,多一点冗长的代码和有意义的变量名:

/** 
* 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 
}