Javascript Javascript自然排序数组/对象并维护索引关联
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3824392/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript natural sort array/object and maintain index association
提问by user396404
I have an array of items as follows in Javascript:
我在 Javascript 中有一个项目数组,如下所示:
var users = Array();
users[562] = 'testuser3';
users[16] = 'testuser6';
users[834] = 'testuser1';
users[823] = 'testuser4';
users[23] = 'testuser2';
users[917] = 'testuser5';
I need to sort that array to get the following output:
我需要对该数组进行排序以获得以下输出:
users[834] = 'testuser1';
users[23] = 'testuser2';
users[562] = 'testuser3';
users[823] = 'testuser4';
users[917] = 'testuser5';
users[16] = 'testuser6';
Notice how it is sorted by the value of the array and the value-to-index association is maintained after the array is sorted (that is critical). I have looked for a solution to this, tried making it, but have hit a wall.
注意它是如何按数组的值排序的,并且在数组排序后维护值到索引的关联(这很关键)。我一直在寻找解决方案,尝试制作它,但遇到了麻烦。
By the way, I am aware that this is technically not an array since that would mean the indices are always iterating 0 through n where n+1 is the counting number proceeding n. However you define it, the requirement for the project is still the same. Also, if it makes a difference, I am NOT using jquery.
顺便说一下,我知道这在技术上不是一个数组,因为这意味着索引总是从 0 到 n 迭代,其中 n+1 是继续 n 的计数。无论您如何定义它,项目的要求仍然相同。另外,如果它有所作为,我不会使用 jquery。
采纳答案by user396404
Using the ideas from the comments, I came up with the following solution. The naturalSort function is something I found on google and I modified it to sort a multidimensional array. Basically, I made the users array a multidimensional array with the first index being the user id and the second index being the user name. So:
使用评论中的想法,我想出了以下解决方案。naturalSort 函数是我在 google 上找到的,我修改了它以对多维数组进行排序。基本上,我将用户数组设为多维数组,第一个索引是用户 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';
I then sorted the array to get the following output:
然后我对数组进行排序以获得以下输出:
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';
The code to do this is below:
执行此操作的代码如下:
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 + '' + nC ).split(nC),
yN = y.replace( re, nC + '' + 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);
回答by Gumbo
The order of the elements of an array is defined by the index. So even if you specify the values in a different order, the values will always be stored in the order of their indices and undefined indices are undefined
:
数组元素的顺序由索引定义。因此,即使您以不同的顺序指定值,这些值也将始终按其索引的顺序存储,未定义的索引是undefined
:
> var arr = [];
> arr[2] = 2;
> arr[0] = 0;
> arr
[0, undefined, 2]
Now if you want to store the pair of index and value, you will need a different data structure, maybe an array of array like this:
现在,如果要存储索引和值对,则需要不同的数据结构,可能是这样的数组数组:
var arr = [
[562, 'testuser3'],
[16, 'testuser6'],
[834, 'testuser1'],
[823, 'testuser4'],
[23, 'testuser2'],
[917, 'testuser5']
];
This can be sorted with this comparison function:
这可以用这个比较函数排序:
function cmp(a, b) {
return a[1].localeCompare(b[1]);
}
arr.sort(cmp);
The result is this array:
结果是这个数组:
[
[834, 'testuser1'],
[23, 'testuser2'],
[562, 'testuser3'],
[823, 'testuser4'],
[917, 'testuser5'],
[16, 'testuser6']
]
回答by s4y
If I understand the question correctly, you're using arrays in a way they are not intended to be used. In fact, the initialization style
如果我正确理解了这个问题,那么您正在以不打算使用数组的方式使用数组。其实初始化风格
// Don't do this!
var array = new Array();
array[0] = 'value';
array[1] = 'value';
array[2] = 'value';
teaches wrong things about the nature and purpose of arrays. An array is an ordered list of items, indexed from zero up. The right way to create an array is with an array literal:
教导错误的关于数组的性质和目的的东西。数组是一个有序的项目列表,从零开始索引。创建数组的正确方法是使用数组文字:
var array = [
'value',
'value',
'value'
]
The indexes are implied based on the order the items are specified. Creating an array and setting users[562] = 'testuser3'
impliesthat there are at least 562 other users in the list, and that you have a reason for only knowing the 563rd at this time.
索引是根据指定项目的顺序隐含的。创建数组和设置users[562] = 'testuser3'
意味着列表中至少有 562 个其他用户,并且您有理由此时只知道第 563 个。
In your case, the index is data, and is does not represent the order of the items in the set. What you're looking for is a map or dictionary, represented in JavaScript by a plain object:
在您的情况下,索引是数据,并且不代表 set 中项目的顺序。您正在寻找的是地图或字典,在 JavaScript 中由普通对象表示:
var users = {
562: 'testuser3',
16: 'testuser6',
834: 'testuser1',
823: 'testuser4',
23: 'testuser2',
917: 'testuser5'
}
Now your set does not have an order, but does have meaningful keys. From here, you can follow galambalazs's adviceto create an array of the object's keys:
现在您的 set没有 order,但确实有有意义的键。从这里,您可以按照galambalazs 的建议创建对象键的数组:
var userOrder;
if (typeof Object.keys === 'function') {
userOrder = Object.keys(users);
} else {
for (var key in users) {
userOrder.push(key);
}
}
…then sort it:
...然后排序:
userOrder.sort(function(a, b){
return users[a].localeCompare(users[b]);
});
回答by gblazex
You can't order arrays like this in Javascript. Your best bet is to make a map for order.
您不能在 Javascript 中对这样的数组进行排序。最好的办法是制作一张地图以便订购。
order = new Array();
order[0] = 562;
order[1] = 16;
order[2] = 834;
order[3] = 823;
order[4] = 23;
order[5] = 917;
In this way, you can have any order you want independently of the keys in the original array. To sort your array use a custom sorting function.
通过这种方式,您可以独立于原始数组中的键拥有任何您想要的顺序。要对数组进行排序,请使用自定义排序函数。
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]
[演示]
回答by kennebec
I'd use map once to make a new array of users, then a second time to return the string you want from the new array.
我会使用 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
*/
If you want to avoid any gaps. use a simple filter on the output-
如果你想避免任何差距。在输出上使用一个简单的过滤器-
u2.map(function(itm, i){
return 'users['+itm+']= testuser'+i;
}).filter(function(itm){return itm}).join('\n');
回答by AutoSponge
Sparse arrays usually spell trouble. You're better off saving key-value pairs in an array as objects (this technique is also valid JSON):
稀疏数组通常会带来麻烦。最好将数组中的键值对保存为对象(此技术也是有效的 JSON):
users = [{
"562": "testuser3"
},{
"16": "testuser6"
}, {
"834": "testuser1"
}, {
"823": "testuser4"
}, {
"23": "testuser2"
}, {
"917": "testuser5"
}];
As suggested, you can use a for loop to map the sorting function onto the array.
按照建议,您可以使用 for 循环将排序函数映射到数组上。
回答by Sean Vieira
Array.prototype.sort()
takes an optional custom comparison function -- so if you dump all of your users
into an array in this manner [ [562, "testuser3"], [16, "testuser6"] ... etc.]
Array.prototype.sort()
采用可选的自定义比较函数——因此,如果您users
以这种方式将所有内容转储到数组中[ [562, "testuser3"], [16, "testuser6"] ... etc.]
Then sort
this array with the following function:
然后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;
}
Then rebuild your users
object. (Which will loose you your sorting.) Or, keep the data in the newly sorted array of arrays, if that will work for your application.
然后重建你的users
对象。(这将使您失去排序。)或者,将数据保存在新排序的数组数组中,如果这对您的应用程序有效。