JS push-объект с динамическими ключами и значениями в массив

У меня есть массив объектов с динамическими ключами и значениями (поэтому не все объекты имеют category_id, размер и т. д.), но я упростил его до этого:

let products_row = [
  {
    id: 1,
    category_id: 11,
    options: {
      'modelName1': {
        size: '2 feet',
        colour: 'red',
        is_new: true
      },
      'modelName2': {
        size: '4 feet',
        colour: 'black',
        is_new: true
      },
    }
  },
  {
    id: 2,
    category_id: 21,
    options: {
      'modelName11': {
        size: '2 feet',
        colour: 'white',
        is_new: false
      },
      'modelName12': {
        size: '4 feet',
        colour: 'white',
        is_new: false
      },
    }
  },
  {
    id: 3,
    category_id: 31,
    options: {
      'modelName21': {
        size: '8 feet',
        colour: 'white',
        is_new: false
      },
      'modelName22': {
        size: '4 feet',
        colour: 'black',
        is_new: true
      },
    }
  },
  {
    id: 4,
    category_id: 41,
    options: {
      'modelName31': {
        size: '8 feet',
        colour: 'red',
        is_new: true
      },
      'modelName32': {
        size: '8 feet',
        colour: 'red',
        is_new: true
      },
    }
  }
]

структура данных результата должна быть такой:

let resultArray = [
  {
        id: 1,
        category_id: 11,
        model: 'modelName1',
        size: '2 feet',
        colour: 'red',
        is_new: true
  },
  {
        id: 1,
        category_id: 11,
        model: 'modelName2',
        size: '4 feet',
        colour: 'black',
        is_new: true
  },
  {
        id: 2,
        category_id: 21,
        model: 'modelName11',
        size: '2 feet',
        colour: 'white',
        is_new: false
 },
 {
        id: 2,
        category_id: 21,
        model: 'modelName12',
        size: '4 feet',
        colour: 'white',
        is_new: false
  },
  {
        id: 3,
        category_id: 31,
        model: 'modelName21',
        size: '8 feet',
        colour: 'white',
        is_new: false
  },
  {
        id: 3,
        category_id: 31,
        model: 'modelName22',
        size: '4 feet',
        colour: 'black',
        is_new: true
  },
  {
        id: 4,
        category_id: 41,
        model: 'modelName31',
        size: '8 feet',
        colour: 'red',
        is_new: true
  },
  {
        id: 4,
        category_id: 41,
        model: 'modelName32',
        size: '8 feet',
        colour: 'red',
        is_new: true
  },
]

Это то, что я пробовал:

let productsData = [];

products_row
.map((product, p) => Object.entries(product.options || {})
.filter((model, i) => {            
    return productsData.push(
      {
        model: model[0],          
        [Object.keys(product).filter(el => delete product.options)[i]]: Object.values(product)[i],
        [Object.keys(model[1] || [])[i]]: Object.values(model[1] || [])[i],
      }
    )
})
)

console.info(productsData)

Но он возвращает не все данные, что ожидается, потому что я не могу понять, как сохранить предыдущие значения ключей:

[
  {      
        model: 'modelName1',
        id: 1,
        size: '2 feet',
  },
  {      
        model: 'modelName2',  
        category_id: 11,     
        colour: 'black',        
  },
  {     
        model: 'modelName11',
        id: 2,
        size: '2 feet',
 },
 {        
        model: 'modelName12',
        category_id: 21,
        colour: 'white',
  },
  {        
        model: 'modelName21',
        id: 3,
        size: '8 feet',
  },
  {        
        model: 'modelName22',
        category_id: 31,
        colour: 'black',
  },
  {        
        model: 'modelName31',
        id: 4,
        size: '8 feet',
  },
  {        
        model: 'modelName32',
        category_id: 41,
        colour: 'red',
  },
]

Я полностью застрял, любая помощь приветствуется. Спасибо.

Поведение ключевого слова "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) для оценки ваших знаний,...
0
0
47
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

вы можете использовать flatMap и map
Что делает flatMap, так это то, что возвращаемый массив map выглядит как

[
[{...1},{...2}],
[{...3},{...4}]
]

это сгладит его и даст

[
{...1},{...2},
{...3},{...4}
]

let products_row = [{id: 1,category_id: 11,options: {'modelName1': {size: '2 feet',colour: 'red',is_new: true},'modelName2': {size: '4 feet',colour: 'black',is_new: true},}},{id: 2,category_id: 21,options: {'modelName11': {size: '2 feet',colour: 'white',is_new: false},'modelName12': {size: '4 feet',colour: 'white',is_new: false},}},{id: 3,category_id: 31,options: {'modelName21': {size: '8 feet',colour: 'white',is_new: false},'modelName22': {size: '4 feet',colour: 'black',is_new: true},}},{id: 4,category_id: 41,options: {'modelName31': {size: '8 feet',colour: 'red',is_new: true},'modelName32': {size: '8 feet',colour: 'red',is_new: true},}}]

let x = products_row.flatMap(({options,...rest}) => Object.entries(options).map(([k,v]) => ({...v,...rest,model:k})))

console.info(x)

cmgchess, ваше решение такое простое! Я не думаю, что я мог бы решить это самостоятельно. Я почему-то пытался решить проблему таким трудным путем LOL Спасибо!

Anna 17.03.2022 18:48

надеюсь, шаги были ясны

cmgchess 17.03.2022 18:49

да спасибо. У меня обычно очень простая структура данных, и я никогда раньше не использовал flatMap, поэтому ваше решение не было для меня очевидным. Никогда не переставай учиться, ха-ха

Anna 17.03.2022 19:17

Довольно сложно анализировать ваше решение и рассуждать о вашей идее, поэтому я не могу исправить ваш код.

Что вы хотите сделать, так это извлечь параметры из каждого объекта и присоединить остальную часть объекта, другими словами, вы хотите выполнить итерацию по каждому параметру для каждой строки продукта.

Есть множество способов добиться этого, вы можете использовать flatMap, как предложил @cmgchess. Легче понять что-то вроде этого:

let result = [];

products_row.forEach(({ options, ...rest }) =>
  Object.values(options).forEach((b) => result.push({ ...rest, ...b })),
);

чем вы :) Увидев ваше решение, я немного изменил его, включив ключ объекта: products_row.forEach(({ options, ...rest }) => Object.entries(options).forEach((k,b) => result.push({ ...rest, ...b[1], ...k[1], model:k[0] })), );

Anna 17.03.2022 19:13

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