Reorganize an array with es6 for items with same id

Viewed 44

Let's say I have an array of products:

const products = [
 { title: 'test product', storefront: {id: 0, title: 'test storefront 1'} },
 { title: 'test product 2', storefront: {id: 0, title: 'test storefront 1'} },
 { title: 'test product 3', storefront: {id: 1, title: 'test storefront 2'} }
]

How would I return a new array that will contain an object for each storefront and all it's products?

For example:

  const storefronsts = [
    {
      storefront: {id: 0, title: 'test storefront 1'}, 
      products: [
        { title: 'test product', storefront: {id: 0, title: 'test storefront 1'} }, 
        { title: 'test product 2', storefront: {id: 0, title: 'test storefront 1'} }
      ]
    },
    {
      storefront: {id: 1, title: 'test storefront 2'}, 
      products: [
        { title: 'test product 3', storefront: {id: 1, title: 'test storefront 2'} }
      ]
    }
  ]
2 Answers

You can use reduce and then just check each storefront id

const rtn = products.reduce((p,c,i,a) => {
    let current = p.find(store => store.storefront.id == c.storefront.id);
    if (!current) { 
        current = { storefront: {id: c.storefront.id, title: c.storefront.title, products: []} }
        p.push(current);
    }

    current.storefront.products.push(c)
    return p;
}, [])

Demo: https://jsfiddle.net/n1pfL8e6/

The output (storefronts Array) can be compared with the requested Array (from the question) using JSON.stringify. The following code returns true for the comparison, whereas the accepted answer returns false.

Original Input:

const products = [{
    title: 'test product',
    storefront: {
        id: 0,
        title: 'test storefront 1'
    }
},
{
    title: 'test product 2',
    storefront: {
        id: 0,
        title: 'test storefront 1'
    }
},
{
    title: 'test product 3',
    storefront: {
        id: 1,
        title: 'test storefront 2'
    }
}
];

Transformation Process:

const pre = {}

products.forEach(product => {

  const storeFrontId = product.storefront.id;
  const { storefront } = product;
  if (pre[storeFrontId]) {
    return pre[storeFrontId].products.push(product);
  } 
  pre[storeFrontId] = { storefront, products: [ product ] }

});

const storefronts = [];

Object.keys(pre).map(key => storefronts.push(pre[key]));
// Alternative, cleaner version:
// Object.values(pre).map(value => storefronts.push(value) );

console.log(storefronts);

Comparing with the original output:

const expected = [
    {
      storefront: {id: 0, title: 'test storefront 1'}, 
      products: [
        { title: 'test product', storefront: {id: 0, title: 'test storefront 1'} }, 
        { title: 'test product 2', storefront: {id: 0, title: 'test storefront 1'} }
      ]
    },
    {
      storefront: {id: 1, title: 'test storefront 2'}, 
      products: [
        { title: 'test product 3', storefront: {id: 1, title: 'test storefront 2'} }
      ]
    }
];

const expectedJSON = JSON.stringify( expected );

Comparing our result with the expected structure:

console.log( JSON.stringify( storefronts ) === expectedJSON );
//=> true
Related