Home > Blockchain >  How can I group matching nested array children when making an array flat in JavaScript?
How can I group matching nested array children when making an array flat in JavaScript?

Time:12-11

I am receiving data from an API that I need to transform into a flatter format with grouped properties.

In this example I have a list of car makes with different tire properties. I am trying to group the car make with each available tire size / width. If both properties match I need combine the records.

Response

[
    {
        carMake: 'Ford',
        tires: [
            {
                brand: 'Dunlap',
                otherKey: 'aaa',
                size: 33,
                width: 12,
            },
            {
                brand: 'Good Year',
                size: 33,
                width: 12,
            },
            {
                brand: 'Continental',
                size: 33,
                width: 11,
            },
            {
                brand: 'Pirelli',
                size: 32,
                width: 12,
            }
        ]
    },
    {
        carMake: 'Chevy',
        tires: [
            {
                brand: 'Dunlap',
                size: 33,
                width: 12,
            },
        ]
    }
]

Desired Result

[
    {
        carMake: 'Ford',
        otherKey: 'aaa',
        brands: ['Dunlap', 'Good Year'],
        size: 33,
        width: 12,
    },
    {
        carMake: 'Ford',
        brands: ['Continental'],
        size: 33,
        width: 11,
    },
    {
        carMake: 'Ford',
        brands: ['Pirelli'],
        size: 32,
        width: 12,
    },
    {
        carMake: 'Chevy',
        brands: ['Dunlap'],
        size: 33,
        width: 12,
    }
]

What I've tried:

I've tried using both flatMap and reduce but I am only able to get the first level complete. Admittedly, I am not the best manipulating JS shapes as I primarily work with C based languages.

apiResponse.flatMap(({carMake, tires}) => tires.map((tire) => ({ carMake, ...tire })));
[{
    carMake: 'Chevy',
    brand: 'Dunlap',
    size: 33,
    width: 12,
}]

CodePudding user response:

const apiResponse = [{"carMake":"Ford","tires":[{"brand":"Dunlap",otherKey:'aaa',"size":33,"width":12},{"brand":"Good Year","size":33,"width":12},{"brand":"Continental","size":33,"width":11},{"brand":"Pirelli","size":32,"width":12}]},{"carMake":"Chevy","tires":[{"brand":"Dunlap","size":33,"width":12}]}]

const r = apiResponse.flatMap(({carMake,tires})=>
  Object.values(
    tires.reduce((a,{brand,size,width,...other})=>{
      let k = [carMake, size, width].join();
      a[k] ??= {carMake, brands: [], size, width};
      (a[k] = {...a[k], ...other}).brands.push(brand);
      return a
    },{})
  )
)

console.log(r)

CodePudding user response:

You can first use find to look for tires with same size, width & carmake.

If not present, insert new object in result array else push new brand in existing object. Something like this:

response = [
    {
        carMake: 'Ford',
        tires: [{"brand":"Dunlap","size":33,"width":12},{"brand":"Good Year","size":33,"width":12},{"brand":"Continental","size":33,"width":11},{"brand":"Pirelli","size":32,"width":12}]
    },
    {
        carMake: 'Chevy',
        tires: [{"brand":"Dunlap","size":33,"width":12}]
    }
]

result=[]
response.forEach(k=> {
    k.tires.forEach(tire=> {

        ans = result.find(o=> o.size==tire.size && o.width==tire.width && k.carMake==o.carMake)

        if(ans){
            ans.brand.push(tire.brand) //in-place array object update
        }else{
            result.push({ carMake: k.carMake, brand: [tire.brand], size: tire.size, width: tire.width})
        }
    })
})
console.log(result)

  • Related