我在Javascript中有以下项目数组:
var users = Array();
users[562] = 'testuser3';
users[16] = 'testuser6';
users[834] = 'testuser1';
users[823] = 'testuser4';
users[23] = 'testuser2';
users[917] = 'testuser5';
我需要对该数组进行排序以获得以下输出:
users[834] = 'testuser1';
users[23] = 'testuser2';
users[562] = 'testuser3';
users[823] = 'testuser4';
users[917] = 'testuser5';
users[16] = 'testuser6';
注意它是如何按数组的值排序的,并且在对数组进行排序后保持value-to-index关联(这很关键)。我已经找到了解决方案,尝试制作它,但已经撞墙了。
顺便说一句,我知道这在技术上不是一个数组,因为这意味着索引总是迭代0到n,其中n + 1是n前面的计数。无论您如何定义,项目的要求仍然相同。此外,如果它有所作为,我不使用jquery。
答案 0 :(得分:23)
数组元素的顺序由索引定义。因此,即使您以不同的顺序指定值,值也将始终按其索引的顺序存储,未定义的索引为undefined
:
> var arr = [];
> arr[2] = 2;
> arr[0] = 0;
> arr
[0, undefined, 2]
现在,如果你想存储这对索引和值,你需要一个不同的数据结构,也许是这样的数组数组:
var arr = [
[562, 'testuser3'],
[16, 'testuser6'],
[834, 'testuser1'],
[823, 'testuser4'],
[23, 'testuser2'],
[917, 'testuser5']
];
可以使用此比较函数对其进行排序:
function cmp(a, b) {
return a[1].localeCompare(b[1]);
}
arr.sort(cmp);
结果是这个数组:
[
[834, 'testuser1'],
[23, 'testuser2'],
[562, 'testuser3'],
[823, 'testuser4'],
[917, 'testuser5'],
[16, 'testuser6']
]
答案 1 :(得分:7)
如果我正确理解了这个问题,您正在以不打算使用的方式使用数组。实际上,初始化风格
// Don't do this!
var array = new Array();
array[0] = 'value';
array[1] = 'value';
array[2] = 'value';
教导关于数组的性质和目的的错误信息。数组是一个有序的项目列表,从零开始索引。创建数组的正确方法是使用数组文字:
var array = [
'value',
'value',
'value'
]
根据指定项目的顺序隐含索引。创建一个数组并设置users[562] = 'testuser3'
意味着列表中至少有562个其他用户,并且您有理由此时只知道563号。
在您的情况下,索引是数据,并且不代表集合中项目的顺序。您正在寻找的是地图或字典,由JavaScript表示普通对象:
var users = {
562: 'testuser3',
16: 'testuser6',
834: 'testuser1',
823: 'testuser4',
23: 'testuser2',
917: 'testuser5'
}
现在您的设置没有订单,但确实有有意义的关键字。从这里开始,您可以按照galambalazs's advice创建对象键的数组:
var userOrder;
if (typeof Object.keys === 'function') {
userOrder = Object.keys(users);
} else {
for (var key in users) {
userOrder.push(key);
}
}
...然后对它进行排序:
userOrder.sort(function(a, b){
return users[a].localeCompare(users[b]);
});
答案 2 :(得分:3)
你不能在Javascript中订购这样的数组。您最好的选择是制作订单地图。
order = new Array();
order[0] = 562;
order[1] = 16;
order[2] = 834;
order[3] = 823;
order[4] = 23;
order[5] = 917;
通过这种方式,您可以独立于原始数组中的键获得任何您想要的顺序。 要对数组进行排序,请使用自定义排序功能。
order.sort( function(a, b) {
if ( users[a] < users[b] ) return -1;
else if ( users[a] > users[b] ) return 1;
else return 0;
});
for ( var i = 0; i < order.length; i++ ) {
// users[ order[i] ]
}
<强> [Demo] 强>
答案 3 :(得分:2)
使用评论中的想法,我提出了以下解决方案。我在google上找到了naturalSort函数,我对其进行了修改以对多维数组进行排序。基本上,我使users数组成为一个多维数组,第一个索引是用户id,第二个索引是用户名。所以:
users[0][0] = 72;
users[0][1] = 'testuser4';
users[1][0] = 91;
users[1][1] = 'testuser2';
users[2][0] = 12;
users[2][1] = 'testuser8';
users[3][0] = 3;
users[3][1] = 'testuser1';
users[4][0] = 18;
users[4][1] = 'testuser7';
users[5][0] = 47;
users[5][1] = 'testuser3';
users[6][0] = 16;
users[6][1] = 'testuser6';
users[7][0] = 20;
users[7][1] = 'testuser5';
然后我对数组进行了排序以获得以下输出:
users_sorted[0][0] = 3;
users_sorted[0][1] = 'testuser1';
users_sorted[1][0] = 91;
users_sorted[1][1] = 'testuser2';
users_sorted[2][0] = 47;
users_sorted[2][1] = 'testuser3';
users_sorted[3][0] = 72;
users_sorted[3][1] = 'testuser4';
users_sorted[4][0] = 20;
users_sorted[4][1] = 'testuser5';
users_sorted[5][0] = 16;
users_sorted[5][1] = 'testuser6';
users_sorted[6][0] = 18;
users_sorted[6][1] = 'testuser7';
users_sorted[7][0] = 12;
users_sorted[7][1] = 'testuser8';
执行此操作的代码如下:
function naturalSort(a, b) // Function to natural-case insensitive sort multidimensional arrays by second index
{
// setup temp-scope variables for comparison evauluation
var re = /(-?[0-9\.]+)/g,
x = a[1].toString().toLowerCase() || '',
y = b[1].toString().toLowerCase() || '',
nC = String.fromCharCode(0),
xN = x.replace( re, nC + '$1' + nC ).split(nC),
yN = y.replace( re, nC + '$1' + nC ).split(nC),
xD = (new Date(x)).getTime(),
yD = xD ? (new Date(y)).getTime() : null;
// natural sorting of dates
if ( yD )
if ( xD < yD ) return -1;
else if ( xD > yD ) return 1;
// natural sorting through split numeric strings and default strings
for( var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++ ) {
oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc];
oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc];
if (oFxNcL < oFyNcL) return -1;
else if (oFxNcL > oFyNcL) return 1;
}
return 0;
}
// Set values for index
var users = Array();
var temp = Array();
users.push(Array('72', 'testuser4'));
users.push(Array('91', 'testuser2'));
users.push(Array('12', 'testuser8'));
users.push(Array('3', 'testuser1'));
users.push(Array('18', 'testuser7'));
users.push(Array('47', 'testuser3'));
users.push(Array('16', 'testuser6'));
users.push(Array('20', 'testuser5'));
// Sort the array
var users_sorted = Array();
users_sorted = users.sort(naturalSort);
答案 4 :(得分:1)
我会使用map一次创建一个新的用户数组, 然后第二次从新数组返回你想要的字符串。
var users= [];
users[562]= 'testuser3';
users[16]= 'testuser6';
users[834]= 'testuser1';
users[823]= 'testuser4';
users[23]= 'testuser2';
users[917]= 'testuser5';
var u2= [];
users.map(function(itm, i){
if(itm){
var n= parseInt(itm.substring(8), 10);
u2[n]= i;
}
});
u2.map(function(itm, i){
return 'users['+itm+']= testuser'+i;
}).join('\n');
/*returned value: (String)
users[834]= testuser1
users[23]= testuser2
users[562]= testuser3
users[823]= testuser4
users[917]= testuser5
users[16]= testuser6
*/
如果你想避免任何差距。在输出上使用简单的过滤器 -
u2.map(function(itm, i){
return 'users['+itm+']= testuser'+i;
}).filter(function(itm){return itm}).join('\n');
答案 5 :(得分:1)
稀疏阵列通常会带来麻烦。最好将数组中的键值对保存为对象(此技术也是有效的JSON):
users = [{
"562": "testuser3"
},{
"16": "testuser6"
}, {
"834": "testuser1"
}, {
"823": "testuser4"
}, {
"23": "testuser2"
}, {
"917": "testuser5"
}];
根据建议,您可以使用for循环将排序函数映射到数组。
答案 6 :(得分:0)
Array.prototype.sort()
采用可选的自定义比较功能 - 因此,如果您以这种方式将所有users
转储到数组中[ [562, "testuser3"], [16, "testuser6"] ... etc.]
然后sort
此数组具有以下函数:
function(comparatorA, comparatorB) {
var userA = comparatorA[1], userB = comparatorB[1]
if (userA > userB) return 1;
if (userA < userB) return -1;
if (userA === userB) return 0;
}
然后重建您的users
对象。 (这将使您的排序失败。)或者,将数据保存在新排序的数组中,如果这对您的应用程序有效。