Home > Back-end >  How to change an Array object format using a group by along with changing the name of the params?
How to change an Array object format using a group by along with changing the name of the params?

Time:10-21

I have recently started working in Javascript and kinda stuck as to how below scenario supposed to work. I have gone through several examples but not able to figure out.

const mobiles = [
    {
        BRAND_NAME: 'Samsung',
        MODEL_NAME: 'Galaxy Note 9',
        MANUFACTURE_DATE: '2021-11-02'
    },
    {
        BRAND_NAME: 'Samsung',
        MODEL_NAME: 'Galaxy S10',
        MANUFACTURE_DATE: '2021-10-02'
    },
    {
        BRAND_NAME: 'Apple',
        MODEL_NAME: 'Iphone X',
        MANUFACTURE_DATE: '2020-11-02'
    }
];

I have to convert the above array object and group by brand's name. The output should look like below -

[{
  "brandname" : 'Samsung',
  "details" : [{
       modelname: 'Galaxy Note 9",
       manufacturedate: '2021-11-02'
      },
      {
       modelname: 'Galaxy S10'
       manufacturedate: '2021-10-02'
      }]
},
{
"brandname" : 'Apple',
  "details" : [{
       modelname: 'IPhone X",
       manufacturedate: '2020-11-02'
      }]
}      
]

I searched around and came across various articles where they say to use map if you want a new Array object. I am confused how to go about this and whether to use map, reduce or any other function.

Any suggestion how to go about it?

CodePudding user response:

Array.prototype.map is useful when you want to create a new array of the same length, where each element in the array relates in some way to the element in the same index in the initial array. In this case, you are creating new arrays which are shorter, so map is not what you need.

Array.prototype.reduce is useful when you want to incrementally create a single value based on the contents of an array. While you could use reduce for this example, I wouldn't recommend it since it would be harder to follow than a simple loop. The reduce function is most useful when working with primitives, since the value it creates incrementally gets overwritten in each iteration.

You may find Array.prototype.filter useful, as this can create a new array from a source array where each element in the new array had to pass some test when being run on an element in the source array.

For example, you might loop through the whole array to gather the unique BRAND_NAME values (there are a few ways to do this), then iterate through each of those values and run first filter and then map on your array in order to first filter it down to only the elements with the matching brand name, and then to change the format of each element.

Here's an example:

const mobiles = [
    {
        BRAND_NAME: 'Samsung',
        MODEL_NAME: 'Galaxy Note 9',
        MANUFACTURE_DATE: '2021-11-02'
    },
    {
        BRAND_NAME: 'Samsung',
        MODEL_NAME: 'Galaxy S10',
        MANUFACTURE_DATE: '2021-10-02'
    },
    {
        BRAND_NAME: 'Apple',
        MODEL_NAME: 'Iphone X',
        MANUFACTURE_DATE: '2020-11-02'
    }
];

const mobileBrands = mobiles.map((el) => el.BRAND_NAME);
const brandNames = [...new Set(mobileBrands)]; // This is one way to remove duplicate values from an Array

// If you need your brands to appear in a particular order, you could sort them here

const mobilesByBrand = [];
for (let brandName of brandNames) {
    const brand = {
        brandname: brandName,
    };

    brand.details = mobiles
        .filter((el) => el.BRAND_NAME === brandName)
        .map((el) => {
            return {
                modelname: el.MODEL_NAME,
                manufacturedate: el.MANUFACTURE_DATE,
            };
        });

    mobilesByBrand.push(brand);
}

console.log(mobilesByBrand);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

You can use Array#reduce with an object to store the models for each brand. To rename properties, you can map over the entries of each object and convert it back to an object with Object.fromEntries.

const mobiles = [
    {
        BRAND_NAME: 'Samsung',
        MODEL_NAME: 'Galaxy Note 9',
        MANUFACTURE_DATE: '2021-11-02'
    },
    {
        BRAND_NAME: 'Samsung',
        MODEL_NAME: 'Galaxy S10',
        MANUFACTURE_DATE: '2021-10-02'
    },
    {
        BRAND_NAME: 'Apple',
        MODEL_NAME: 'Iphone X',
        MANUFACTURE_DATE: '2020-11-02'
    }
];
const res = Object.values(mobiles.reduce((acc, {BRAND_NAME, ...rest})=>{
  (acc[BRAND_NAME] ??= {brandname: BRAND_NAME, details: []}).details.push(
    Object.fromEntries(Object.entries(rest)
      .map(([k,v])=>[k.toLowerCase().replace('_', ''), v])));
  return acc;
}, {}));
console.log(res);
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related