0

I have an array of objects with dynamic keys and values (so not all objects have category_id, size and so on) but I simplified it to this:

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
      },
    }
  }
]

the result data structure needs to be like this:

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
  },
]

This is what I have tried:

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.log(productsData)

But it returns not all data, which is expected because I can't figure out how to keep previous key-values:

[
  {      
        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',
  },
]

I am completely stuck, any help is appreciated. Thank you.

2 Answers 2

1

you can use flatMap and map
What flatMap does is if the returned array of map looks like

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

it will flatten it and give

[
{...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.log(x)

Sign up to request clarification or add additional context in comments.

3 Comments

cmgchess, your solution is so simple! I don't think I could solve it on my own. For some reason I tried to solve the problem going such difficult way LOL Thank you!
hope the steps were clear
yes, thank you. I usually have very simple data structure and have never used flatMap before that's why your solution wasn't obvious for me. Never stop learning haha
1

It is quite hard to analyze your solution and reason about your idea, so I cannot fix your code.

What you want to do is to extract options from each object and attach the rest of object, in other words you want to iterate over each option for each product row.

There are numerous ways to achieve this, you can use flatMap as @cmgchess suggested. Easier to understand is something like this:

let result = [];

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

1 Comment

than you :) Seeing your solution I modified it a bit to include object key as well: products_row.forEach(({ options, ...rest }) => Object.entries(options).forEach((k,b) => result.push({ ...rest, ...b[1], ...k[1], model:k[0] })), );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.