Javascript Javascript按两个字段对数组进行排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6129952/
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 sort array by two fields
提问by Mark
grouperArray.sort(function (a, b) {
var aSize = a.gsize;
var bSize = b.gsize;
var aLow = a.glow;
var bLow = b.glow;
console.log(aLow + " | " + bLow);
return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;
});
So the above code sorts the array by gsize - smallest to largest. It works good. But if the gsize is the same I would like it to then sort by glow.
所以上面的代码按 gsize 对数组进行排序 - 从最小到最大。它运作良好。但如果 gsize 相同,我希望它按发光排序。
Thanks.
谢谢。
回答by anmorozov23
grouperArray.sort(function (a, b) {
return a.gsize - b.gsize || a.glow - b.glow;
});
shorter version
较短的版本
回答by Chris Eberle
grouperArray.sort(function (a, b) {
var aSize = a.gsize;
var bSize = b.gsize;
var aLow = a.glow;
var bLow = b.glow;
console.log(aLow + " | " + bLow);
if(aSize == bSize)
{
return (aLow < bLow) ? -1 : (aLow > bLow) ? 1 : 0;
}
else
{
return (aSize < bSize) ? -1 : 1;
}
});
回答by Vinorth
grouperArray.sort((a, b) => a.gsize - b.gsize || a.glow - b.glow);
Even shorter version using arrow syntax!
使用箭头语法的更短版本!
回答by nihlton
I realize this was asked some time ago, but I thought I would add my solution.
我意识到这是前一段时间被问到的,但我想我会添加我的解决方案。
This function generates sort methods dynamically. simply supply each sortable child property name, prepended with +/- to indicate ascending or descending order. Super re-usable, and it doesn't need to know anything about the data structure you've put together. Could be made idiot proof - but doesn't seem necessary.
此函数动态生成排序方法。只需提供每个可排序的子属性名称,加上 +/- 以指示升序或降序。超级可重用,它不需要知道你放在一起的数据结构。可以证明白痴 - 但似乎没有必要。
function getSortMethod(){
var _args = Array.prototype.slice.call(arguments);
return function(a, b){
for(var x in _args){
var ax = a[_args[x].substring(1)];
var bx = b[_args[x].substring(1)];
var cx;
ax = typeof ax == "string" ? ax.toLowerCase() : ax / 1;
bx = typeof bx == "string" ? bx.toLowerCase() : bx / 1;
if(_args[x].substring(0,1) == "-"){cx = ax; ax = bx; bx = cx;}
if(ax != bx){return ax < bx ? -1 : 1;}
}
}
}
example usage:
用法示例:
items.sort(getSortMethod('-price', '+priority', '+name'));
items.sort(getSortMethod('-price', '+priority', '+name'));
this would sort items
with lowest price
first, with ties going to the item with the highest priority
. further ties are broken by the item name
这将首先items
以最低的方式排序price
,关系将指向具有最高的项目priority
。进一步的联系被项目打破name
where items is an array like:
其中 items 是一个数组,如:
var items = [
{ name: "z - test item", price: "99.99", priority: 0, reviews: 309, rating: 2 },
{ name: "z - test item", price: "1.99", priority: 0, reviews: 11, rating: 0.5 },
{ name: "y - test item", price: "99.99", priority: 1, reviews: 99, rating: 1 },
{ name: "y - test item", price: "0", priority: 1, reviews: 394, rating: 3.5 },
{ name: "x - test item", price: "0", priority: 2, reviews: 249, rating: 0.5 } ...
];
live demo: http://gregtaff.com/misc/multi_field_sort/
现场演示:http: //gregtaff.com/misc/multi_field_sort/
EDIT: Fixed issue with Chrome.
编辑:修复了 Chrome 的问题。
回答by John Green
I expect the ternaryoperator ((aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;)
has you confused. You should check out the link to understand it better.
我希望三元运算符((aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;)
让您感到困惑。您应该查看链接以更好地理解它。
Until then, here's your code blown out into full if/else.
在那之前,这里是你的 if/else 代码。
grouperArray.sort(function (a, b) {
if (a.gsize < b.gsize)
{
return -1;
}
else if (a.gsize > b.gsize)
{
return 1;
}
else
{
if (a.glow < b.glow)
{
return -1;
}
else if (a.glow > b.glow)
{
return 1;
}
return 0;
}
});
回答by The_Black_Smurf
Here's an implementation for those who may want something more generic that would work with any number of fields.
对于那些可能想要更通用的东西来处理任意数量的字段的人来说,这是一个实现。
Array.prototype.sortBy = function (propertyName, sortDirection) {
var sortArguments = arguments;
this.sort(function (objA, objB) {
var result = 0;
for (var argIndex = 0; argIndex < sortArguments.length && result === 0; argIndex += 2) {
var propertyName = sortArguments[argIndex];
result = (objA[propertyName] < objB[propertyName]) ? -1 : (objA[propertyName] > objB[propertyName]) ? 1 : 0;
//Reverse if sort order is false (DESC)
result *= !sortArguments[argIndex + 1] ? 1 : -1;
}
return result;
});
}
Basically, you may specify any number of property name / sort direction:
基本上,您可以指定任意数量的属性名称/排序方向:
var arr = [{
LastName: "Doe",
FirstName: "John",
Age: 28
}, {
LastName: "Doe",
FirstName: "Jane",
Age: 28
}, {
LastName: "Foo",
FirstName: "John",
Age: 30
}];
arr.sortBy("LastName", true, "FirstName", true, "Age", false);
//Will return Jane Doe / John Doe / John Foo
arr.sortBy("Age", false, "LastName", true, "FirstName", false);
//Will return John Foo / John Doe / Jane Doe
回答by Benjamin Portman
Here is an implementation that uses recursion to sort by any number of sort fields from 1 to infinite. You pass it a results array which is an array of result objects to sort, and a sorts array which is an array of sort objects defining the sort. Each sort object must have a "select" key for the key name that it sorts by and an "order" key which is a string indicating "ascending" or "descending".
这是一个实现,它使用递归按从 1 到无限的任意数量的排序字段进行排序。你传递给它一个结果数组,它是一个要排序的结果对象数组,一个 sorts 数组是一个定义排序的排序对象数组。每个排序对象都必须有一个用于排序的键名的“选择”键和一个“排序”键,它是一个指示“升序”或“降序”的字符串。
sortMultiCompare = (a, b, sorts) => {
let select = sorts[0].select
let order = sorts[0].order
if (a[select] < b[select]) {
return order == 'ascending' ? -1 : 1
}
if (a[select] > b[select]) {
return order == 'ascending' ? 1 : -1
}
if(sorts.length > 1) {
let remainingSorts = sorts.slice(1)
return this.sortMultiCompare(a, b, remainingSorts)
}
return 0
}
sortResults = (results, sorts) => {
return results.sort((a, b) => {
return this.sortMultiCompare(a, b, sorts)
})
}
// example inputs
const results = [
{
"LastName": "Doe",
"FirstName": "John",
"MiddleName": "Bill"
},
{
"LastName": "Doe",
"FirstName": "Jane",
"MiddleName": "Bill"
},
{
"LastName": "Johnson",
"FirstName": "Kevin",
"MiddleName": "Bill"
}
]
const sorts = [
{
"select": "LastName",
"order": "ascending"
},
{
"select": "FirstName",
"order": "ascending"
},
{
"select": "MiddleName",
"order": "ascending"
}
]
// call the function like this:
let sortedResults = sortResults(results, sorts)
回答by silex
grouperArray.sort(function (a, b) {
var aSize = a.gsize;
var bSize = b.gsize;
var aLow = a.glow;
var bLow = b.glow;
console.log(aLow + " | " + bLow);
return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : ( (aLow < bLow ) ? -1 : (aLow > bLow ) ? 1 : 0 );
});
回答by Tim Williams
grouperArray.sort(function (a, b) {
var aSize = a.gsize;
var bSize = b.gsize;
var aLow = a.glow;
var bLow = b.glow;
console.log(aLow + " | " + bLow);
return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : (aLow < bLow) ? -1 : (aLow > bLow) ? 1 : 0); });
回答by Deliaz
Here is the solution for the case, when you have a priority sort key, which might not exist in some particular items, so you have to sort by fallback keys.
这是这种情况的解决方案,当您有一个优先排序键时,它可能不存在于某些特定项目中,因此您必须按回退键排序。
An input data example (id2is priority sort key):
输入数据示例(id2是优先排序键):
const arr = [
{id: 1},
{id: 2, id2: 3},
{id: 4},
{id: 3},
{id: 10, id2: 2},
{id: 7},
{id: 6, id2: 1},
{id: 5},
{id: 9, id2: 2},
{id: 8},
];
And the output should be:
输出应该是:
[ { id: 6, id2: 1 },
{ id: 9, id2: 2 },
{ id: 10, id2: 2 },
{ id: 2, id2: 3 },
{ id: 1 },
{ id: 3 },
{ id: 4 },
{ id: 5 },
{ id: 7 },
{ id: 8 } ]
The comparator function will be like:
比较器函数将类似于:
arr.sort((a,b) => {
if(a.id2 || b.id2) {
if(a.id2 && b.id2) {
if(a.id2 === b.id2) {
return a.id - b.id;
}
return a.id2 - b.id2;
}
return a.id2 ? -1 : 1;
}
return a.id - b.id
});
P.S. In case if .idof .id2can be zeros, consider to use typeof
.
PS在情况下,如果.ID的.id2可以为零,可以考虑使用typeof
。