Reputation: 735
I'm in the midst of learning how to use the lodash library, but I've bumped into a problem that I don' think I know how to solve. I want to sort a nested array that looks like this with lodash:
"results": [
{
"id": "12345",
"name": "toy123",
"date_created": "2017-08-29T16:10:37Z",
"date_last_modified": "2019-01-29T17:19:36Z",
"prices": [
{
"currency": "USD",
"amount": "100.00"
},
{
"currency": "EUR",
"amount": "88.23"
},
]
},
{
"id": "54321",
"name": "toy321",
"date_created": "2017-08-29T16:10:37Z",
"date_last_modified": "2019-01-29T17:19:36Z",
"prices": [
{
"currency": "USD",
"amount": "80.00"
},
{
"currency": "EUR",
"amount": "70.58"
},
]
},
]
I want to sort the array based on the prices
array that is nested in the given array. The sorting will take consideration of the prices.currency
and prices.amount
and produce the output as below where the given array is sorted ascendingly based on USD
and amount
. And another problem I have is that the prices.amount
is a string, not a number.
[
{
"id": "54321",
"name": "toy321",
"date_created": "2017-08-29T16:10:37Z",
"date_last_modified": "2019-01-29T17:19:36Z",
"prices": [
{
"currency": "USD",
"amount": "80.00"
},
{
"currency": "EUR",
"amount": "70.58"
},
]
},
{
"id": "12345",
"name": "toy123",
"date_created": "2017-08-29T16:10:37Z",
"date_last_modified": "2019-01-29T17:19:36Z",
"prices": [
{
"currency": "USD",
"amount": "100.00"
},
{
"currency": "EUR",
"amount": "88.23"
},
]
},
]
Many thanks in advance for your kindness and of course your time.
Upvotes: 3
Views: 603
Reputation: 6063
The _.sortBy()
method does not support a custom comparator, you should use Array.prototype.sort()
instead. You don't need to parse prices.amount
either, String.prototype.localeCompare()
can do the comparison for you, it supports strings with numeric values.
Putting it all together, your implementation might look something like this:
results.sort((a, b) => {
const priceA = _.find(a.prices, { currency: 'USD' });
const priceB = _.find(b.prices, { currency: 'USD' });
return priceA.amount.localeCompare(priceB.amount, undefined, { numeric: true });
});
Upvotes: 6
Reputation: 5707
and optimise by caching the price lookup which will otherwise be performed on each item multiple times..
const results = [
{
"id": "12345",
"name": "toy123",
"date_created": "2017-08-29T16:10:37Z",
"date_last_modified": "2019-01-29T17:19:36Z",
"prices": [
{ "currency": "USD", "amount": "100.00" },
{ "currency": "EUR", "amount": "88.23" },
]
},
{
"id": "54321",
"name": "toy321",
"date_created": "2017-08-29T16:10:37Z",
"date_last_modified": "2019-01-29T17:19:36Z",
"prices": [
{ "currency": "USD", "amount": "80.00" },
{ "currency": "EUR", "amount": "70.58" },
]
},
];
function sortResults(results, curr) {
return results
.map(result => ([result, result.prices.find(price => price.currency === curr).amount - 0]))
.sort((a, b) => a[1] - b[1])
.map(res => res[0]);
}
console.log(sortResults(results, "USD").map(res => res.name));
Upvotes: 0
Reputation: 21638
No need for external libraries like loadash.
const arr = [
{
"id": "12345",
"name": "toy123",
"date_created": "2017-08-29T16:10:37Z",
"date_last_modified": "2019-01-29T17:19:36Z",
"prices": [
{
"currency": "USD",
"amount": "100.00"
},
{
"currency": "EUR",
"amount": "88.23"
},
]
},
{
"id": "54321",
"name": "toy321",
"date_created": "2017-08-29T16:10:37Z",
"date_last_modified": "2019-01-29T17:19:36Z",
"prices": [
{
"currency": "USD",
"amount": "80.00"
},
{
"currency": "EUR",
"amount": "70.58"
},
]
},
];
const naturalSort = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }).compare;
arr.sort((a,b) => naturalSort(a.prices.find(p => p.currency === 'USD').amount, b.prices.find(p => p.currency === 'USD').amount));
console.log(arr);
Upvotes: 4