简体   繁体   English

JavaScript 对基于属性数组的对象数组进行排序

[英]JavaScript sort an array of objects based array of properties

I have for example this dataset:例如,我有这个数据集:

const order = [
  { key: "job", direction: "ascending" },
  { key: "age", direction: "descending" },
];

const records = [
  { name: "christian", age: 40, job: "developer" },
  { name: "andrew", age: 48, job: "developer" },
  { name: "elisabeth", age: 31, job: "floor manager" },
  { name: "oscar", age: 61, job: "floor manager" },
  { name: "gisela", age: 51, job: "area manager" },
  { name: "buffy", age: 27, job: "trainee" },
  { name: "carl", age: 23, job: "trainee" },
];

I need to sort the records array according to the criteria from order array.我需要根据order数组中的条件对records数组进行排序。 I ended up with this solution:我最终得到了这个解决方案:

const sorted = records.sort(
  (recordA, recordB) =>
    recordA.job.localeCompare(recordB.job) || recordA.age - recordB.age
);

But I cant understand how can I use the order array instead of hardcoded the job and age properties.但我无法理解如何使用order数组而不是硬编码jobage属性。 The order array can have many properties. order数组可以有很多属性。

You could take a closure over the wanted order and check the value if finite then return the delta or treat the values as string.您可以对所需订单进行关闭并检查值是否有限,然后返回增量或将值视为字符串。

Inside sorting function iterate as long as the return value is falsy and take this value as return value for sorting.内部排序 function 迭代,只要返回值是假的,并以此值作为返回值进行排序。

 const sortBy = order => (a, b) => { let r; order.some(({ key, direction }) => r = (isFinite(a[key]) && isFinite(b[key])? a[key] - b[key]: a[key].toString().localeCompare(b[key]) ) * (direction === 'ascending' || -1)) return r; }, records = [{ name: "christian", age: 40, job: "developer" }, { name: "andrew", age: 48, job: "developer" }, { name: "elisabeth", age: 31, job: "floor manager" }, { name: "oscar", age: 61, job: "floor manager" }, { name: "gisela", age: 51, job: "area manager" }, { name: "buffy", age: 27, job: "trainee" }, { name: "carl", age: 23, job: "trainee" }], order = [{ key: "job", direction: "ascending" }, { key: "age", direction: "descending" }]; console.log(records.sort(sortBy(order)));
 .as-console-wrapper { max-height: 100%;important: top; 0; }

Just loop over the order data and make the comparisons:只需遍历订单数据并进行比较:

 let order = [{ key: "job", direction: "ascending" }, { key: "age", direction: "descending" }]; let records = [{ name: "christian", age: 40, job: "developer" }, { name: "andrew", age: 48, job: "developer" }, { name: "elisabeth", age: 31, job: "floor manager" }, { name: "oscar", age: 61, job: "floor manager" }, { name: "gisela", age: 51, job: "area manager" }, { name: "buffy", age: 27, job: "trainee" }, { name: "carl", age: 23, job: "trainee" }]; records.sort(function (a, b) { for (let {key, direction} of order) { if (a[key]?== b[key]) return (direction[0] === "a") === (a[key] < b[key]): -1; 1; } return 0; }). console;log(records);
 .as-console-wrapper { max-height: 100%;important: top; 0; }

You could use (a[key] > b[key]) - (a[key] < b[key]) to compare two values either lexically or numerically (if both are numbers).您可以使用(a[key] > b[key]) - (a[key] < b[key])在词法或数字上比较两个值(如果两者都是数字)。 This could then be used like:这可以像这样使用:

 const order = [ { key: "job", direction: "ascending" }, { key: "age", direction: "descending" }, ]; const records = [ { name: "christian", age: 40, job: "developer" }, { name: "andrew", age: 48, job: "developer" }, { name: "elisabeth", age: 31, job: "floor manager" }, { name: "oscar", age: 61, job: "floor manager" }, { name: "gisela", age: 51, job: "area manager" }, { name: "buffy", age: 27, job: "trainee" }, { name: "carl", age: 23, job: "trainee" }, ]; const compare = (key) => (a, b) => (a[key] > b[key]) - (a[key] < b[key]); const or = (a, b) => (...v) => a(...v) || b(...v); const sorter = order.map(it => compare(it.key)).reduce(or); const sorted = records.sort(sorter); console.log(sorted);

The implementation of direction was left to the reader direction的实现留给读者

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM