#javascript #reduce #array.prototype.map
#javascript #уменьшить #array.prototype.map
Вопрос:
У меня есть следующий код со следующими массивами. Я хочу перебрать их оба, извлечь некоторые данные и поместить их в конечный массив. Я могу это сделать, но содержимое дублируется. Я пытался читать о reduce, но не совсем понимаю это, и не уверен, правильное ли это решение. Я также настроил jsfiddle
https://jsfiddle.net/anders_kitson/Lcqn6fgd/
var lineItems = [{
id: 'li_1HyhAZHk5l44uIELgsMWqHqB',
object: 'item',
amount_subtotal: 7500,
amount_total: 7500,
currency: 'cad',
description: 'The Spencer',
price: [Object],
quantity: 1
},
{
id: 'li_1HyhAZHk5l44uIELeNUsiZPu',
object: 'item',
amount_subtotal: 7500,
amount_total: 7500,
currency: 'cad',
description: 'The Gertie',
price: [Object],
quantity: 1
}
]
var arr = [{
id: 'prod_IS1wY1JvSv2CJg',
object: 'product',
active: true,
attributes: [],
created: 1606248785,
description: 'Shelf Set',
images: [
'https://files.stripe.com/links/fl_test_raNEqk9ZhzX3WdQsnvXX4gFq'
],
livemode: false,
metadata: {},
name: 'The Spencer',
statement_descriptor: null,
type: 'service',
unit_label: null,
updated: 1606248785
},
{
id: 'prod_IS299dMnC13Ezo',
object: 'product',
active: true,
attributes: [],
created: 1606249543,
description: 'Shelf Set',
images: [
'https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe'
],
livemode: false,
metadata: {},
name: 'The Gertie',
statement_descriptor: null,
type: 'service',
unit_label: null,
updated: 1606249543
}
];
let productArr = [];
arr.map((item) => {
lineItems.map((line) => {
productArr.push({
image: item.images[0],
name: item.name,
price: line.amount_total,
});
});
});
console.log(productArr);
Это результат, который я получаю, где вы можете видеть, что массив повторяет значения, и я знаю, что я закодировал его таким образом, я просто не знаю, как это исправить.
[{
image: "https://files.stripe.com/links/fl_test_raNEqk9ZhzX3WdQsnvXX4gFq",
name: "The Spencer",
price: 7500
}, {
image: "https://files.stripe.com/links/fl_test_raNEqk9ZhzX3WdQsnvXX4gFq",
name: "The Spencer",
price: 7500
}, {
image: "https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe",
name: "The Gertie",
price: 7500
}, {
image: "https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe",
name: "The Gertie",
price: 7500
}]
Чтобы было более понятно, это тот результат, который я хочу
[{
image: "https://files.stripe.com/links/fl_test_raNEqk9ZhzX3WdQsnvXX4gFq",
name: "The Spencer",
price: 7500
}, {
image: "https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe",
name: "The Gertie",
price: 7500
},
]
Я попробовал предложение в комментариях со следующим
let b
arr.map((item) => {
b = lineItems.map((line) => {
return {
image: item.images[0],
name: item.name,
price: line.amount_total,
};
});
});
но он возвращает одни и те же дважды
[{
image: "https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe",
name: "The Gertie",
price: 7500
}, {
image: "https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe",
name: "The Gertie",
price: 7500
}]
Комментарии:
1.
map
возвращает массив. Используйте это вместоpush
перехода к новому массиву.2. Что находится
arr
на первой карте?3. Я взял массивы из того, что сгенерировано в моем коде. На самом деле я выполняю запрос к stripe для вывода arr и выполняю другой запрос к stripe для LineItems, поэтому существуют отдельные массивы
4. @HereticMonkey если map возвращает массив, как мне получить все необходимые данные в нем в виде объекта, как видно из моего вывода?
5. Возвращает объект из функции, переданной
map
. Я настоятельно рекомендую ознакомиться с документацией MDN поmap
.
Ответ №1:
Хотя это и не выражено непосредственно в вашем вопросе, похоже, что вы хотите выполнить объединение в javascript. Единственное, что я вижу, связывающее эти два понятия, — это «название» в продуктах и «описание» в позициях. Так что сделайте объединение циклов по этому поводу.
Вот несколько примеров кода, использующих ваш пример, но сокращенных только до того, что имеет отношение к делу:
var lineItems = [
{ amount_total: 7500, description: 'The Spencer' },
{ amount_total: 7500, description: 'The Gertie' }
]
var arr = [
{ images: ['Spencer Image 1'], name: 'The Spencer' },
{ images: ['Gertie Image 1'], name: 'The Gertie' }
]
let joined = arr
.flatMap(a => lineItems.map(li => ({a, li})))
.filter(obj => obj.a.name == obj.li.description)
.map(obj => ({
image: obj.a.images[0],
name: obj.a.name,
price: obj.li.amount_total
}));
console.log(joined);
Будучи циклическим соединением, оно может быть не столь эффективным. Выполнить хэш-соединение немного сложнее. Вы можете просмотреть исходный код моего разрабатываемого проекта fluent-data, или вам может быть даже полезно использовать его напрямую, если вы можете следовать документации.
Комментарии:
1. 1 для Clippy, я даже не читал дальше 🙂
Ответ №2:
Вы можете использовать один вызов map и ссылаться на свой второй lineItems
массив либо по индексу, если вы знаете, что два массива имеют одинаковую длину и порядок
const output = arr.map((o, i) => ({
name: o.name,
image: o.images[0],
price: lineItems[i].amount_total}
));
или с помощью find()
для извлечения соответствующего объекта.
const outputUsingFind = arr.map(o => {
const lineItem = lineItems.find(item => item.description === o.name);
// ** add lineItem valid check here **
return {
name: o.name,
image: o.images[0],
price: lineItem.amount_total};
});
var lineItems = [{amount_subtotal: 7500,amount_total: 700,description: 'The Spencer',},{amount_subtotal: 7500,amount_total: 500,description: 'The Gertie',}];
var arr = [{images: ['spencer image'],name: 'The Spencer',},{images: ['gertie image'],name: 'The Gertie'}];
// since your arrays are ordered the same you can access the second object using
// the index passed from map.
const output = arr.map((o, i) => ({
name: o.name,
image: o.images[0],
price: lineItems[i].amount_total}
));
console.log(output);
// if the two arrays are not in the same order you can use find() to retrieve
// the second object by property (you'll need to check
const outputUsingFind = arr.map(o => {
const lineItem = lineItems.find(item => item.description === o.name);
// ** add lineItem valid check here **
return {
name: o.name,
image: o.images[0],
price: lineItem.amount_total};
});
console.log(outputUsingFind);
.as-console-wrapper { max-height: 100% !important; top: 0; }