#javascript #arrays #sorting #filter #lodash
#javascript #массивы #сортировка #Фильтр #Lodash
Вопрос:
Я нахожусь в процессе изучения того, как использовать библиотеку Lodash, но я столкнулся с проблемой, которую, как мне кажется, я не знаю, как решить. Я хочу отсортировать вложенный массив, который выглядит следующим образом, с помощью 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"
},
]
},
]
Я хочу отсортировать массив на основе prices
массива, который вложен в данный массив. Сортировка будет учитывать prices.currency
и prices.amount
и выдаст результат, как показано ниже, где данный массив сортируется по возрастанию на основе USD
и amount
. И еще одна проблема, с которой я сталкиваюсь, заключается в том, что prices.amount
это строка, а не число.
[
{
"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"
},
]
},
]
Заранее большое спасибо за вашу доброту и, конечно, за ваше время.
Комментарии:
1. Можете ли вы уточнить часть сортировки. Что вы подразумеваете под сортировкой по долларам США и базовой сумме?
2. price.amount — это не проблема, потому что вы получите гибкость первого parseInt, а затем сравните
3. @binariedMe это означает, что массив сортируется на основе суммы в валюте в долларах США.
4. Ну, тогда другие уже ответили в соответствии с вашим требованием. Я думаю, они должны работать нормально.
Ответ №1:
_.sortBy()
Метод не поддерживает пользовательский компаратор, вы должны использовать Array.prototype.sort()
вместо этого. Вам prices.amount
также не нужно разбирать, String.prototype.localeCompare()
я могу выполнить сравнение за вас, он поддерживает строки с числовыми значениями.
Собрав все это вместе, ваша реализация может выглядеть примерно так:
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 });
});
Комментарии:
1. Это позволит создать новую функцию сравнения для каждого элемента в массиве, посмотрите на мое решение ниже, чтобы увидеть, как кэшировать функцию сравнения для повышения производительности.
2. Вы уверены, что смотрите на мое решение?
3. Извините, я увидел «cache» и увидел другой ответ с «cache». Я не знал о
Intl.Collator
спасибо, что поделились!
Ответ №2:
Нет необходимости во внешних библиотеках, таких как 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);
Комментарии:
1. какую-либо конкретную причину вы использовали
sensitivity: 'base'
?2. На самом деле не для этого примера, это, вероятно, взято из копирования и вставки в этом примере. Я всегда использую его при создании intl collator, чтобы он не учитывал регистр.
Ответ №3:
и оптимизировать путем кэширования поиска цен, который в противном случае будет выполняться для каждого элемента несколько раз..
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));