Does anyone know how to group an array of objects by an object key and then create a new array of objects based on the grouping? For example, I have an array of Build objects as below and I want to group by products and create another object of colors and price based on that.
build = [
{
'Product': 'Cabinets',
'Color': 'Blue',
},
{
'Product': 'CounterTop',
'Color': 'White',
},
{
'Product': 'Cabinets',
'Color': 'Yellow',
},
{
'Product': 'Cabinets',
'Color': 'Yellow',
}
]
And I want it like this
[
{
'Product':'Cabinet',
'color' : { 'Blue','Yellow' }
},
{
'Product':'CounterTop',
'color' : { 'White' }
}
]
I wrote a code to archive it but I am not getting the result as expected.
build.forEach(pr => {
if (pr.Product in result) {
result[pr['Product']]['Color'] = pr['Color'];
}
else {
result[pr['Product']] = {
'Product': pr['Product'],
'Color': pr['Color']
}
}
});
Above code returns
[
{
'Product':'Cabinet',
'color' : 'Yellow'
},
{
'Product':'CounterTop',
'color' : 'White'
}
]
Expecting 'color' : { 'Blue','Yellow' } in your output is wrong. Objects are key-value pairs of data.
Instead, you want color to be an array. I adjusted your code:
build.forEach(pr => {
if (pr.Product in result) {
result[pr['Product']]['Color'].push(pr['Color']);
} else {
result[pr['Product']] = {
'Product': pr['Product'],
'Color': [pr['Color']]
}
}
});
Now think about how you can prevent duplicate values in the array. @Lissy93's answer helps with that by using findIndex.
Here's a working version. Hope it helps :)
const builds = [
{ 'Product': 'Cabinets', 'Color': 'Blue' },
{ 'Product': 'CounterTop', 'Color': 'White' },
{ 'Product': 'Cabinets', 'Color': 'Yellow' },
{ 'Product': 'Cabinets', 'Color': 'Yellow' }
];
const results = [];
builds.forEach((build) => {
const index = results.findIndex((b) => b.Product === build.Product);
if (index === -1) {
results.push({Product: build.Product, Color: [ build.Color ]});
} else {
results[index] = {Product: build.Product, Color: [ ...results[index].Color, build.Color ]}
}
});
console.log(results);
The main issue in your code, was that you're mixing up arrays and key-value-pairs for color. KVP's look like { color: 'red' }, whereas arrays would be: [ 'red', 'blue'].
Use this strategy:
Array#map and Array#filter to build desired dataSee demo below:
const builds = [ { 'Product': 'Cabinets', 'Color': 'Blue' }, { 'Product': 'CounterTop', 'Color': 'White' }, { 'Product': 'Cabinets', 'Color': 'Yellow' }, { 'Product': 'Cabinets', 'Color': 'Yellow' } ],
output = [...new Set(builds.map(({Product}) => Product))]
.map(Product =>
({
Product,
Color:builds.filter(({Product:P}) => P === Product)
.map(({Color}) => Color)
})
);
console.log(output);