我有一个Javascript对象数组,我想通过一个属性进行交叉兼容排序,该属性总是一个正整数,末尾有一个可选的单个字母。我正在寻找一种至少适用于Firefox 3和Internet Explorer 8的解决方案。我最接近这种排序功能的是:
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,big
1010,foo,小
15,foo,小
1A,吧,大
1B,吧,小
1C,吧,小
1D,酒吧,大
1E,酒吧,大
1F,酒吧,大
1G,foo,小
2,foo,小
23,foo,小
23C,foo,小
3,foo,小
但是,我希望arrayOfObjects按以下顺序打印出来:
1,foo,big
1A,吧,大
1B,吧,小
1C,吧,小
1D,酒吧,大
1E,酒吧,大
1F,酒吧,大
1G,foo,小
2,foo,小
3,foo,小
15,foo,小
23,foo,小
23C,foo,小
1010,foo,小
鉴于此,我如何修复上述功能,以便对象按编号排序为主键,字母为辅助键?提前感谢您的帮助。
答案 0 :(得分: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;
}
})());
这个想法是将键分成数字和字符串部分。
编辑(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;
});
有点简单。
答案 1 :(得分:0)
您不需要从一串数字中解析整数 -
如果两个数字串匹配,则值无关紧要,您可以查看可能的字母。
如果数字不匹配,则从另一个中减去一个数字会强制数字。
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];
});
答案 2 :(得分: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
}