如何在 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));
};

