如何按嵌套对象属性对 JavaScript 对象数组进行排序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5073799/
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 a JavaScript array of objects by nested object property?
提问by VerizonW
I have this function to sort a JavaScript array of objects based on a property:
我有这个函数可以根据属性对 JavaScript 对象数组进行排序:
// arr is the array of objects, prop is the property to sort by
var sort = function (prop, arr) {
arr.sort(function (a, b) {
if (a[prop] < b[prop]) {
return -1;
} else if (a[prop] > b[prop]) {
return 1;
} else {
return 0;
}
});
};
It works with arrays like this:
它适用于这样的数组:
sort('property', [
{property:'1'},
{property:'3'},
{property:'2'},
{property:'4'},
]);
But I want to be able to sort also by nested properties, for example something like:
但我也希望能够按嵌套属性进行排序,例如:
sort('nestedobj.property', [
{nestedobj:{property:'1'}},
{nestedobj:{property:'3'}},
{nestedobj:{property:'2'}},
{nestedobj:{property:'4'}}
]);
However this doesn't work because it is not possible to do something like object['nestedobj.property'], it should be object['nestedobj']['property'].
但是这不起作用,因为不可能做类似的事情object['nestedobj.property'],它应该是object['nestedobj']['property']。
Do you know how could I solve this problem and make my function work with properties of nested objects?
你知道我如何解决这个问题并使我的函数与嵌套对象的属性一起工作吗?
Thanks in advance
提前致谢
采纳答案by user113716
You can split the propon ., and iterate over the Array updating the aand bwith the next nested property during each iteration.
您可以分割prop上.遍历数组更新,并a与b每个迭代过程中的下一个嵌套属性。
Example:http://jsfiddle.net/x8KD6/1/
示例:http : //jsfiddle.net/x8KD6/1/
var sort = function (prop, arr) {
prop = prop.split('.');
var len = prop.length;
arr.sort(function (a, b) {
var i = 0;
while( i < len ) { a = a[prop[i]]; b = b[prop[i]]; i++; }
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
});
return arr;
};
回答by Anurag
Instead of passing the property as a string, pass a function that can retrieve the property from the top level object.
不是将属性作为字符串传递,而是传递一个可以从顶级对象检索属性的函数。
var sort = function (propertyRetriever, arr) {
arr.sort(function (a, b) {
var valueA = propertyRetriever(a);
var valueB = propertyRetriever(b);
if (valueA < valueB) {
return -1;
} else if (valueA > valueB) {
return 1;
} else {
return 0;
}
});
};
Invoke as,
调用为,
var simplePropertyRetriever = function(obj) {
return obj.property;
};
sort(simplePropertyRetriever, { .. });
Or using a nested object,
或者使用嵌套对象,
var nestedPropertyRetriever = function(obj) {
return obj.nestedObj.property;
};
sort(nestedPropertyRetriever, { .. });
回答by rat
Use Array.prototype.sort()with a custom compare function to do the descending sort first:
使用Array.prototype.sort()自定义比较函数首先进行降序排序:
champions.sort(function(a, b) { return b.level - a.level }).slice(...
Even nicer with ES6:
使用 ES6 更好:
champions.sort((a, b) => b.level - a.level).slice(...
回答by a8m
You can use Agile.jsfor this kind of things.
Actually you pass an expression instead of callback, it's handle nested properties and javascript expression in a very nice-ish way.
您可以将Agile.js用于此类事情。
实际上,您传递的是表达式而不是回调,它以一种非常漂亮的方式处理嵌套属性和 javascript 表达式。
Usage:_.orderBy(array, expression/callback, reverse[optional])
用法:_.orderBy(array, expression/callback, reverse[optional])
Example:
例子:
var orders = [
{ product: { price: 91.12, id: 1 }, date: new Date('01/01/2014') },
{ product: { price: 79.21, id: 2 }, date: new Date('01/01/2014') },
{ product: { price: 99.90, id: 3 }, date: new Date('01/01/2013') },
{ product: { price: 19.99, id: 4 }, date: new Date('01/01/1970') }
];
_.orderBy(orders, 'product.price');
// → [orders[3], orders[1], orders[0], orders[2]]
_.orderBy(orders, '-product.price');
// → [orders[2], orders[0], orders[1], orders[3]]
回答by Mas
if you have array of objects like
如果你有像这样的对象数组
const objs = [{
first_nom: 'Lazslo',
last_nom: 'Jamf',
moreDetails: {
age: 20
}
}, {
first_nom: 'Pig',
last_nom: 'Bodine',
moreDetails: {
age: 21
}
}, {
first_nom: 'Pirate',
last_nom: 'Prentice',
moreDetails: {
age: 22
}
}];
you can use simply
你可以简单地使用
nestedSort = (prop1, prop2 = null, direction = 'asc') => (e1, e2) => {
const a = prop2 ? e1[prop1][prop2] : e1[prop1],
b = prop2 ? e2[prop1][prop2] : e2[prop1],
sortOrder = direction === "asc" ? 1 : -1
return (a < b) ? -sortOrder : (a > b) ? sortOrder : 0;
}
and call it
并称之为
for direct objects
对于直接对象
objs.sort(nestedSort("last_nom"));
objs.sort(nestedSort("last_nom", null, "desc"));
for nested objects
对于嵌套对象
objs.sort(nestedSort("moreDetails", "age"));
objs.sort(nestedSort("moreDetails", "age", "desc"));
回答by Chandu
Try this (used a recursive function to get nested value, you can pass the nested property as nestedobj.property): You can use this for any level of hierarchy
试试这个(使用递归函数来获取嵌套值,您可以将嵌套属性作为nestedobj.property 传递):您可以将其用于任何层次结构
// arr is the array of objects, prop is the property to sort by
var getProperty = function(obj, propNested){
if(!obj || !propNested){
return null;
}
else if(propNested.length == 1) {
var key = propNested[0];
return obj[key];
}
else {
var newObj = propNested.shift();
return getProperty(obj[newObj], propNested);
}
};
var sort = function (prop, arr) {
arr.sort(function (a, b) {
var aProp = getProperty(a, prop.split("."));
var bProp = getProperty(a, prop.split("."));
if (aProp < bProp) {
return -1;
} else if (aProp > bProp) {
return 1;
} else {
return 0;
}
});
};
回答by diewland
This is my modify code.
这是我的修改代码。
// arr is the array of objects, prop is the property to sort by
var s = function (prop, arr) {
// add sub function for get value from obj (1/2)
var _getVal = function(o, key){
var v = o;
var k = key.split(".");
for(var i in k){
v = v[k[i]];
}
return v;
}
return arr.sort(function (a, b) {
// get value from obj a, b before sort (2/2)
var aVal = _getVal(a, prop);
var bVal = _getVal(b, prop);
if (aVal < bVal) {
return -1;
} else if (aVal > bVal) {
return 1;
} else {
return 0;
}
});
};
回答by jessegavin
Would this meet your needs?
这会满足您的需求吗?
// arr is the array of objects, prop is the property to sort by
var sort = function (nestedObj, prop, arr) {
arr.sort(function (a, b) {
if (a[nestedObj][prop] < b[nestedObj][prop]) {
return -1;
} else if (a[nestedObj][prop] > b[nestedObj][prop]) {
return 1;
} else {
return 0;
}
});
};

