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)