У меня есть два массива объектов JavaScript:
const types = [
{
id: 1,
name: 'Paint',
unit: 'L',
},
{
id: 2,
name: 'Resin',
unit: 'mL',
},
{
id: 3,
name: 'Fiberglass',
unit: 'yd',
}
];
const items = [
{
id: 1,
type_id: 1,
name: 'Brand x paint',
qty: 5,
},
{
id: 2,
type_id: 1,
name: 'Brand y paint',
supplier: 'brand y',
qty: 3,
},
{
id: 3,
type_id: 2,
name: 'Brand x resin',
qty: 5,
},
{
id: 3,
type_id: 2,
name: 'Brand y resin',
qty: 2,
},
{
id: 3,
type_id: 2,
name: 'Brand z resin',
qty: 3,
},
{
id: 3,
type_id: 2,
name: 'Brand x fiberglass',
qty: 7,
},
{
id: 3,
type_id: 2,
name: 'Brand y fiberglass',
qty: 9,
},
];
Я хочу создать новый массив с массивом типов с дополнительным свойством, которое представляет собой сумму количеств для каждого соответствующего типа. Я придумал сопоставление массива типов, и внутри функции я назначаю новое свойство, например totalQty, которое равно отфильтрованным элементам типа, а затем уменьшаю их с помощью сумматора. Что-то вроде этого, что ужасно неправильно где-то вокруг фильтрующей части:
const itemTypes = types.map( (type) => {
type.total_qty = items
.filter((items) => items.type_id === type.id)
.reduce((sum, item) => sum += item.qty, 0)
}
)
Я просто хочу, чтобы вышеупомянутое сработало, но если есть лучшие способы добавить свойство total_quantity рядом с типом, тогда я открыт для предложений. Заранее спасибо!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вам не хватает начального значения аккумулятора в reduce.
const itemsType = types.map( (type) => {
const temp = items;
type.total_qty = temp
.filter( item => item.type_id === type.id)
.reduce( (acc, item) => acc + item.qty, 0); // value missing here
}
)
Я тестировал на консоли Chrome, но получил только 3 значения undefined.
что вы имеете в виду? результат должен быть в types. Переменная itemsType всегда будет неопределенной, поскольку вы создаете свойство в каждом значении массива types с именем total_qty.
О, теперь я понял. Я ожидал, что новый массив объектов будет присвоен itemsType. Но все же этого достаточно, спасибо за ответ.
Рад помочь :)
Проблема в том, что вы используете map без return в его обратном вызове, но вместо этого мутировать данного массива. Таким образом, map возвращает значения undefined, в то время как в то же время ваш массив types был обновлен (но не выведен).
Вот немного более эффективный метод, использующий Map, чтобы избежать вложенных итераций. Таким образом, он работает с временной сложностью На) вместо O (n²).
Он также позволяет избежать изменения исходных объектов type, но создает новые объекты (с дополнительным свойством) во вновь созданном массиве:
const types = [ { id: 1, name: 'Paint', unit: 'L', }, { id: 2, name: 'Resin', unit: 'mL', }, { id: 3, name: 'Fiberglass', unit: 'yd', } ];
const items = [ { id: 1, type_id: 1, name: 'Brand x paint', qty: 5, }, { id: 2, type_id: 1, name: 'Brand y paint', supplier: 'brand y', qty: 3, }, { id: 3, type_id: 2, name: 'Brand x resin', qty: 5, }, { id: 3, type_id: 2, name: 'Brand y resin', qty: 2, }, { id: 3, type_id: 2, name: 'Brand z resin', qty: 3, }, { id: 3, type_id: 2, name: 'Brand x fiberglass', qty: 7, }, { id: 3, type_id: 2, name: 'Brand y fiberglass', qty: 9, }, ];
// Map keyed by type_id and with the extended type object as value
// (initialised as 0)
const map = new Map(types.map( type => [type.id, {...type, total_qty: 0 }] ));
// Add the quantities from the items to the appropriate map-value
items.forEach(item => map.get(item.type_id).total_qty += item.qty);
// Extract the map values
const itemTypes = Array.from(map.values());
console.info(itemTypes); Более эффективной альтернативой было бы создание объекта поиска с количествами по идентификатору:
const types = [ { id: 1, unit: 'L', name: 'Paint', }, { id: 2, unit: 'mL', name: 'Resin', }, { id: 3, unit: 'yd', name: 'Fiberglass', } ];
const items = [ { id: 1, type_id: 1, qty: 5, name: 'Brand x paint', }, { id: 2, type_id: 1, qty: 3, name: 'Brand y paint', supplier: 'brand y', }, { id: 3, type_id: 2, qty: 5, name: 'Brand x resin', }, { id: 3, type_id: 2, qty: 2, name: 'Brand y resin', }, { id: 3, type_id: 2, qty: 3, name: 'Brand z resin', }, { id: 3, type_id: 2, qty: 7, name: 'Brand x fiberglass', }, { id: 3, type_id: 2, qty: 9, name: 'Brand y fiberglass', }, ];
const qtys = items.reduce((obj, item) =>
(obj[item.type_id] = (obj[item.type_id] || 0) + item.qty, obj), {})
const itemTypes = types.map(type => ({ ...type, total_qty: qtys[type.id] }))
console.info( JSON.stringify( itemTypes ).replace(/},/g, '},\n ') )
console.info( qtys )Для получения информации о синтаксисе распространения в объектных литералах: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals
похоже, что вам просто не хватает
, 0)в конце сокращения