Reputation: 21
I discovered _.reduce however it only keeps 1 of set of information. What option should be used to combine like information?
[
{
fruit: 'apple',
'color': 'red'
},
{
fruit: 'apple',
'color': 'green'
},
{
fruit: 'pear',
'color': 'yellow'
},
{
fruit: 'pear',
'color': 'green'
}
]
My desired outcome would be:
var items = [
{
fruit: 'apple',
'color': 'red', 'green'
},
{
fruit: 'pear',
'color': 'green', 'yellow'
}
]
The current code I have using NodeJS is:
let result = Object.values(json.reduce((c, {fruit,...r}) => {
c[fruit] = c[fruit] || {fruit};
c[fruit] = Object.assign(c[fruit], r);
return c;
}, {}));
Upvotes: 2
Views: 93
Reputation: 11001
Use simple forEach
and build the object of unique keys and get the values using Object.values
.
const data = [
{
fruit: "apple",
color: "red"
},
{
fruit: "apple",
color: "green"
},
{
fruit: "pear",
color: "yellow"
},
{
fruit: "pear",
color: "green"
}
];
const res = {};
data.forEach(
item =>
(res[item.fruit] =
item.fruit in res
? { ...res[item.fruit], color: [...res[item.fruit].color, item.color] }
: { fruit: item.fruit, color: [item.color] })
);
const output = Object.values(res);
console.log(output);
Upvotes: 0
Reputation: 12035
This is an approach that runs in time O(n) instead of O(n^2):
const arr = [
{
fruit: 'apple',
'color': 'red',
},
{
fruit: 'apple',
'color': 'green',
},
{
fruit: 'pear',
'color': 'yellow',
},
{
fruit: 'pear',
'color': 'green',
},
];
const map = arr.reduce((acc, o) => {
if (acc[o.fruit]) {
acc[o.fruit].push(o.color);
} else {
acc[o.fruit] = [o.color];
}
return acc;
}, {});
const result = Object.keys(map).map(k => ({ fruit: k, colors: map[k] }));
console.log(result);
return result;
Note that, as noted in Nick's answer, the difference won't make a difference for a small array, but if the array is large, or the transformation is itself wrapped in a loop, it may matter.
Upvotes: 2
Reputation: 16576
You can use the Array reduce
method for this. Assuming your array isn't super long, using the find
method on each iteration shouldn't be too expensive. If it's a super long array, you might instead opt for an intermediate object that has hash table efficiency. Probably not necessary, though.
const arr = [
{
fruit: 'apple',
'color': 'red'
},
{
fruit: 'apple',
'color': 'green'
},
{
fruit: 'pear',
'color': 'yellow'
},
{
fruit: 'pear',
'color': 'green'
}
];
const combined = arr.reduce((acc, el) => {
const fruit = acc.find(item => item.fruit === el.fruit);
if (fruit) {
fruit.colors.push(el.color)
} else {
acc.push({ fruit: el.fruit, colors: [el.color] });
}
return acc;
}, []);
console.log(combined);
Upvotes: 1