如何在 JavaScript 中对具有多个字段值的对象数组进行排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11379361/
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
How to sort an array of objects with multiple field values in JavaScript
提问by Colin Houghton
I found a great method to sort an array of objects based on one of the properties as defined at:
我找到了一种很好的方法,可以根据以下定义的属性之一对对象数组进行排序:
Sort array of objects by string property value in JavaScript
在 JavaScript 中按字符串属性值对对象数组进行排序
Using that function works perfectly for a single sort (on all browsers), and even a sort within another sort EXCEPT using Google Chrome! Here is Ege ?zcan's great sort routine for arrays of objects
使用该函数非常适用于单一排序(在所有浏览器上),甚至是另一种排序中的排序,除了使用谷歌浏览器!这是 Ege ?zcan 对对象数组的出色排序例程
function dynamicSort(property) {
return function (a,b) {
return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
}
}
Using an array named "Data" (of course, my array has many more object pairs)...
使用名为“Data”的数组(当然,我的数组有更多的对象对)...
var Data = [{Category: "Business", Value: "ABC"},{Category:"Personal", Value:"XYZ"}];
I can get a proper sort where the order is listed as all the values within each category by doing this...
通过这样做,我可以得到一个正确的排序,其中顺序被列为每个类别中的所有值......
Data.sort(dynamicSort("Value"));
Data.sort(dynamicSort("Category"));
By first sorting on Value
, and then by Category
, my array puts all values in sorted order with all the Business-base values listed first and then all the Personal-based values. Perfect! Except in Chrome where the data is sorted properly by category, but the order of the values within each category seems rather random.
首先按 排序Value
,然后按排序Category
,我的数组按排序顺序放置所有值,首先列出所有基于业务的值,然后列出所有基于个人的值。完美的!除了在 Chrome 中,数据按类别正确排序,但每个类别中值的顺序似乎相当随机。
Does any one know of a better way to do a sort within a sort that would also work in Chrome?
有没有人知道在 Chrome 中也可以使用的排序中进行排序的更好方法?
回答by Ege ?zcan
I created a multi-parameter version of that dynamicSort function:
我创建了该 dynamicSort 函数的多参数版本:
function dynamicSort(property) {
return function (obj1,obj2) {
return obj1[property] > obj2[property] ? 1
: obj1[property] < obj2[property] ? -1 : 0;
}
}
function dynamicSortMultiple() {
/*
* save the arguments object as it will be overwritten
* note that arguments object is an array-like object
* consisting of the names of the properties to sort by
*/
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
/* try getting a different result from 0 (equal)
* as long as we have extra properties to compare
*/
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
}
I created an array as follows:
我创建了一个数组,如下所示:
var arr = [
{a:"a",b:"a",c:"a"},
{a:"b",b:"a",c:"b"},
{a:"b",b:"a",c:"a"},
{a:"b",b:"a",c:"b"},
{a:"b",b:"b",c:"a"},
{a:"b",b:"b",c:"b"},
{a:"b",b:"b",c:"a"},
{a:"b",b:"b",c:"b"},
{a:"b",b:"b",c:"a"},
{a:"b",b:"b",c:"b"},
{a:"b",b:"b",c:"a"},
{a:"c",b:"b",c:"b"},
{a:"c",b:"c",c:"a"}
];
and it worked when I did,
当我这样做时它起作用了
arr.sort(dynamicSortMultiple("c","b","a"));
And here is a working example: http://jsfiddle.net/ZXedp/
这是一个工作示例:http: //jsfiddle.net/ZXedp/
回答by tfmontague
The easiest way to perform a Javascript Multi-Criteria Sort (or Multi-Parameter Sort), is to use .sort
, concatenate the multiple parameters together, and compare the two stings.
执行 Javascript 多条件排序(或多参数排序)的最简单方法是使用.sort
,将多个参数连接在一起,然后比较两个字符串。
For example:
例如:
data.sort(function (a, b) {
var aConcat = a["property1"] + a["property2"];
var bConcat = b["property1"] + b["property2"];
if (aConcat > bConcat) {
return 1;
} else if (aConcat < bConcat) {
return -1;
} else {
return 0;
}
});
I've included a JsFiddle Script here: http://jsfiddle.net/oahxg4u3/6/
我在这里包含了一个 JsFiddle 脚本:http: //jsfiddle.net/oahxg4u3/6/
回答by Teun D
You may also want to have a look at thenBy.js: https://github.com/Teun/thenBy.js
您可能还想看看 thenBy.js:https: //github.com/Teun/thenBy.js
It allows you to use the standard Array.sort, but with firstBy().thenBy().thenBy() style.
它允许您使用标准的 Array.sort,但使用 firstBy().thenBy().thenBy() 样式。
回答by Enrico D.
I now this post is quite old, anyway I found it today and quoting Ege ?zcan, I improved his excellent solution implementing DESC-ASC SQL-Like functionality for anyone interested (http://jsfiddle.net/ZXedp/65/):
我现在这篇文章已经很老了,无论如何我今天找到了它并引用了Ege ?zcan,我改进了他的优秀解决方案,为任何感兴趣的人实现了 DESC-ASC SQL-Like 功能(http://jsfiddle.net/ZXedp/65/):
function dynamicSortMultiple() {
var props=[];
/*Let's separate property name from ascendant or descendant keyword*/
for(var i=0; i < arguments.length; i++){
var splittedArg=arguments[i].split(/ +/);
props[props.length]=[splittedArg[0], (splittedArg[1] ? splittedArg[1].toUpperCase() : "ASC")];
}
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length ;
/*Cycle on values until find a difference!*/
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i][0], props[i][1])(obj1, obj2);
i++;
}
return result;
}
}
/*Base function returning -1,1,0 for custom sorting*/
function dynamicSort(property, isAscDesc) {
return function (obj1,obj2) {
if(isAscDesc==="DESC"){
return ((obj1[property] > obj2[property]) ? (-1) : ((obj1[property] < obj2[property]) ? (1) : (0)));
}
/*else, if isAscDesc==="ASC"*/
return ((obj1[property] > obj2[property]) ? (1) : ((obj1[property] < obj2[property]) ? (-1) : (0)));
}
}
call the function by something like this:
通过这样的方式调用函数:
arr.sort(dynamicSortMultiple("c DESC","b Asc","a"));
回答by agershun
Here is my solution. It faster than lodash's _.sortBy()multi-column sort function in about two times (see http://jsperf.com/multi-column-sort. I generate text of sorting function, then use it in standard .sort(). It works in Chrome and Firefox as well.
这是我的解决方案。它比 lodash 的_.sortBy()多列排序函数快大约两倍(参见http://jsperf.com/multi-column-sort。我生成排序函数的文本,然后在标准.sort() 中使用它。它也适用于 Chrome 和 Firefox。
function multiColumnSort(arr,sf) {
var s = '';
sf.forEach(function(f,idx) {
s += 'if(arguments[0].'+f+'>arguments[1].'+f+')return 1;';
s += 'else if(arguments[0].'+f+'==arguments[1].'+f+')';
s += (idx < sf.length-1)? '{' : 'return 0';
});
s += Array(sf.length).join('}')+';return -1';
return arr.sort(new Function(s));
};