Нужна помощь во вложении функций массива в JavaScript

У меня есть два массива объектов 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 рядом с типом, тогда я открыт для предложений. Заранее спасибо!

похоже, что вам просто не хватает , 0) в конце сокращения

Slai 08.12.2018 17:24
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
54
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вам не хватает начального значения аккумулятора в 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.

jp06 08.12.2018 17:57

что вы имеете в виду? результат должен быть в types. Переменная itemsType всегда будет неопределенной, поскольку вы создаете свойство в каждом значении массива types с именем total_qty.

Bargros 08.12.2018 17:58

О, теперь я понял. Я ожидал, что новый массив объектов будет присвоен itemsType. Но все же этого достаточно, спасибо за ответ.

jp06 08.12.2018 18:02

Рад помочь :)

Bargros 08.12.2018 18:04
Ответ принят как подходящий

Проблема в том, что вы используете 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

Другие вопросы по теме