i'd like to sort an array by two fields while providing a desired number to sort them by. i tried using lodash but haven't got the desired results.
for example
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});
the desired result would be
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}
];
any ideas would be greatly appreciated
How about simply use _.sortBy of lodash??
_.sortBy(data, [a=> Math.abs(a.score - 21), a=> Math.abs(a.average - 50)])
Isn't this enough?
EDIT
Well, Yes! if you need this sorting (execution) from one place and with only (exactly that 2) 2 nested fields, then this ole liner is ok, but if you are calling from several places and with diff fields (nested) with closest value, then you can wrap this in a function, prepare the itarees dynamically and pass it to sortBy.
Here is a working example for that:
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>
However key, closest value can be passes in more shorter format like
{score: 21, average: 50}, in that case the logic to generate iteratees
needs to adjust accordingly, so it will became:
_.map(fields, (v,k)=> o=> Math.abs(v - o[k]))
And you need to call it with a single object (as shown above), here is the call for that:
sortByClosest(data, {score: 21, average: 50});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With