我想按两个字段对数组进行排序,同时提供所需的数字对其进行排序。我尝试使用lodash,但没有得到想要的结果。
例如
const data = [
{name: 'first', score: 22, average: 59},
{name: 'second', score: 34, average: 83},
{name: 'third', score: 40, average: 24},
{name: 'fourth', score: 29, average: 49},
{name: 'fifth', score: 23, average: 55}
];
// call function like this
sortByTwoFields({field:'score', number:21}, {field:'average', number:50});
期望的结果将是
const result = [
{name: 'fifth', score: 23, average: 55},
{name: 'fourth', score: 29, average: 49},
{name: 'first', score: 22, average: 59},
{name: 'third', score: 40, average: 24},
{name: 'second', score: 34, average: 83}
];
任何想法将不胜感激
答案 0 :(得分:1)
仅使用_.sortBy
中的lodash
怎么样?
_.sortBy(data, [a=> Math.abs(a.score - 21), a=> Math.abs(a.average - 50)])
这还不够吗?
编辑
是的,是的!如果您需要从一个位置进行排序(执行)并且仅(恰好有2个)2个嵌套字段,则可以使用此ole衬套,但是如果您从多个位置进行调用并且具有最接近值的diff字段(嵌套),则您可以将其包装在函数中,动态地准备itarees并将其传递给sortBy
。
这是一个可行的示例:
var data = [
{name: 'first', score: 22, average: 59},
{name: 'second', score: 34, average: 83},
{name: 'second', score: 34, average: 80},
{name: 'third', score: 40, average: 24},
{name: 'fourth', score: 29, average: 49},
{name: 'fifth', score: 23, average: 55}
];
function sortByClosest(arr, ...fields) {
//this will create array of callbacks, similar to what user in first example
let iteratees = fields.map(f => o => Math.abs(f.number - o[f.field]));
return _.sortBy(arr, iteratees);
}
//pass data for "arr" argument, and all other
//sort key/closest-value for fields array argument
var res = sortByClosest(data, {field:'score', number:21},{field:'average',number:50});
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
但是,最接近的值可以更短的格式传递,例如
{score: 21, average: 50}
,在这种情况下,生成迭代的逻辑
需要进行相应的调整,因此它将变为:
_.map(fields, (v,k)=> o=> Math.abs(v - o[k]))
并且您需要使用单个对象来调用它(如上所示),这是对此的调用:
sortByClosest(data, {score: 21, average: 50});
答案 1 :(得分:0)
由于fourth
的总差为9,而first
的总差为10,因此您期望的结果似乎略有偏离。下面的函数称为sortByTwoFields(data, {field:'score', number:21}, {field:'average', number:50})
。您可以为对象添加weight
属性的优先级,否则默认为1。
function sortByTwoFields (data, info1, info2) {
if (! ("weight" in info1)) {
info1.weight = 1;
}
if (! ("weight" in info2)) {
info2.weight = 1;
}
return data.sort(function (a, b) {
var adiff1 = a[info1.field] - info1.number;
var adiff2 = a[info2.field] - info2.number;
var bdiff1 = b[info1.field] - info1.number;
var bdiff2 = b[info2.field] - info2.number;
return Math.abs(adiff1) * info1.weight + Math.abs(adiff2) * info2.weight - Math.abs(bdiff1) * info1.weight - Math.abs(bdiff2) * info2.weight;
});
}
答案 2 :(得分:0)
我不认为您的预期结果是正确的,因为第四项的总差异较小。
无论如何,该函数将计算出值和给定数字之间的总和,然后按该总和进行排序。
function sortByTwoFields(data, field1, field2) {
data.sort(function (a, b) {
// Work out difference of two fields and add them together to get the total
var totalDifferenceA = Math.abs(field1.number - a[field1.field]) + Math.abs(field2.number - a[field2.field]);
var totalDifferenceB = Math.abs(field1.number - b[field1.field]) + Math.abs(field2.number - b[field2.field]);
// If a has a smaller total then b it should come first
return totalDifferenceA - totalDifferenceB;
});
}
const data = [
{name: 'first', score: 22, average: 59},
{name: 'second', score: 34, average: 83},
{name: 'third', score: 40, average: 24},
{name: 'fourth', score: 29, average: 49},
{name: 'fifth', score: 23, average: 55}
];
sortByTwoFields(data, {field: 'score', number: 21}, {field: 'average', number: 50});
console.log(data);
答案 3 :(得分:0)
通过按任意数量的字段(而不只是两个)进行排序,可以很容易地使它通用:
fname:"/tmp/table1.csv"
tname: "table1"
/ how do I save table tname to file fname?