如何通过嵌套对象属性对 JavaScript 对象数组进行排序?
Posted
技术标签:
【中文标题】如何通过嵌套对象属性对 JavaScript 对象数组进行排序?【英文标题】:How to sort a JavaScript array of objects by nested object property? 【发布时间】:2022-01-18 13:13:17 【问题描述】:我有这个函数可以根据属性对 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;
);
;
它适用于这样的数组:
sort('property', [
property:'1',
property:'3',
property:'2',
property:'4',
]);
但我也希望能够按嵌套属性进行排序,例如:
sort('nestedobj.property', [
nestedobj:property:'1',
nestedobj:property:'3',
nestedobj:property:'2',
nestedobj:property:'4'
]);
但是这行不通,因为不可能做类似object['nestedobj.property']
的事情,它应该是object['nestedobj']['property']
。
您知道如何解决这个问题并让我的函数使用嵌套对象的属性吗?
提前致谢
【问题讨论】:
【参考方案1】:这能满足您的需求吗?
// 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;
);
;
【讨论】:
【参考方案2】:不要将属性作为字符串传递,而是传递一个可以从***对象中检索属性的函数。
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;
);
;
调用为,
var simplePropertyRetriever = function(obj)
return obj.property;
;
sort(simplePropertyRetriever, .. );
或者使用嵌套对象,
var nestedPropertyRetriever = function(obj)
return obj.nestedObj.property;
;
sort(nestedPropertyRetriever, .. );
【讨论】:
【参考方案3】:您可以在.
上拆分prop
,并在每次迭代期间使用下一个嵌套属性更新a
和b
的数组。
示例: 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;
;
【讨论】:
感谢这个工作,并且比建议的其他选项更快。 @VerizonW:很高兴它成功了。是的,我喜欢尽可能避免函数调用。让事情变得活泼。 :o) 这似乎不适用于不同长度的属性值。例如。nestedobj:property:'g', nestedobj:property:'F', nestedobj:property:'abcd', nestedobj:property:'abba'
【参考方案4】:
试试这个(使用递归函数获取嵌套值,您可以将嵌套属性作为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;
);
;
【讨论】:
【参考方案5】:这是我的修改代码。
// 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;
);
;
【讨论】:
【参考方案6】:您可以使用Agile.js 处理这类事情。 实际上你传递一个表达式而不是回调,它以一种非常好的方式处理嵌套属性和 javascript 表达式。
用法:_.orderBy(array, expression/callback, reverse[optional])
示例:
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]]
【讨论】:
【参考方案7】:使用Array.prototype.sort()
和自定义比较函数首先进行降序排序:
champions.sort(function(a, b) return b.level - a.level ).slice(...
使用 ES6 更好:
champions.sort((a, b) => b.level - a.level).slice(...
【讨论】:
【参考方案8】:如果你有类似的对象数组
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
];
你可以简单地使用
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;
然后调用它
对于直接对象
objs.sort(nestedSort("last_nom"));
objs.sort(nestedSort("last_nom", null, "desc"));
对于嵌套对象
objs.sort(nestedSort("moreDetails", "age"));
objs.sort(nestedSort("moreDetails", "age", "desc"));
【讨论】:
【参考方案9】:var objectsArr = [
nestedobj:property:'1',
nestedobj:property:'3',
nestedobj:property:'2',
nestedobj:property:'4'
];
function getFromPath(obj, path)
let r = obj;
path.forEach(key => r = r[key])
return r
function sortObjectsArr(objectsArray, ...path)
objectsArray.sort((a, b) => getFromPath(a, path) - getFromPath(b, path))
sortObjectsArr(objectsArr, 'nestedobj', 'property');
console.log(objectsArr);
不幸的是,我没有找到任何好的方法来使用参数来访问嵌套对象的属性。 想提一下,如果键在传递的对象中可用,可以进行一些检查,但这取决于谁以及如何实现。
【讨论】:
以上是关于如何通过嵌套对象属性对 JavaScript 对象数组进行排序?的主要内容,如果未能解决你的问题,请参考以下文章