I have such array of objects:
[{id: 1, name: 'Apple', category: 'Fruit'}
{id: 2, name: 'Melon', category: 'Fruit'}
{id: 3, name: 'iPhone', category: 'Phone'}
{id: 4, name: 'Samsung Galaxy Note 8', category: 'Phone'}
{id: 5, name: 'Playstation 5', category: 'Entertainment'}]
and what I wanted to achieve is to combine product names by category and show them like:
Fruit
Apple
Melon
Phone
iPhone
Samsung Galaxy Note 8
Entertainment
Playstation 5
So, what I tried to achieve that is
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
const products = [{id: 1, name: 'Apple', category: 'Fruit'}
{id: 2, name: 'Melon', category: 'Fruit'}
{id: 3, name: 'iPhone', category: 'Phone'}
{id: 4, name: 'Samsung Galaxy Note 8', category: 'Phone'}
{id: 5, name: 'Playstation 5', category: 'Entertainment'}]
console.log(groupBy([products], 'category'));
You have to adjust your reduce a bit:
const mapping = arr.reduce((obj, entry) => {
obj[entry.category] = obj[entry.category] ? [...obj[entry.category], entry] : [entry]
return obj;
}, {})
resulting in
{
Entertainment: [{
category: "Entertainment",
id: 5,
name: "Playstation 5"
}],
Fruit: [{
category: "Fruit",
id: 1,
name: "Apple"
}, {
category: "Fruit",
id: 2,
name: "Melon"
}],
Phone: [{
category: "Phone",
id: 3,
name: "iPhone"
}, {
category: "Phone",
id: 4,
name: "Samsung Galaxy Note 8"
}]
}
And you can adjust what you want to save by changing entry to a desired value of entry.
I would approach your groupBy method like this:
function groupBy(data, key, value) {
const groups = {};
data.forEach(element => {
let subkey = element[key];
if (!(subkey in groups)) {
groups[subkey] = [element[value]];
} else {
groups[subkey].push(element[value]);
}
});
return groups;
}
console.log(groupBy(products, "category", "name")
You loop over every element, and if the specified key is not already in the groups object it will be added. if it's already added we just add the new element to the array.
This is an example return value of the groupBy function:
{
Fruit: [ 'Apple', 'Melon' ],
Phone: [ 'iPhone', 'Samsung Galaxy Note 8' ],
Entertainment: [ 'Playstation 5' ]
}
To generate HTML code
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
const products = [{id: 1, name: 'Apple', category: 'Fruit'},
{id: 2, name: 'Melon', category: 'Fruit'},
{id: 3, name: 'iPhone', category: 'Phone'},
{id: 4, name: 'Samsung Galaxy Note 8', category: 'Phone'},
{id: 5, name: 'Playstation 5', category: 'Entertainment'}];
const groups = groupBy(products, 'category');
const html = Object.keys(groups).reduce((code, cat) => {
const inner = groups[cat].reduce((i, product) => {
return i + `<p>${product.name}</p>`;
}, '');
return code + `<div><h2>${cat}</h2>${inner}</div>`;
}, '');
document.getElementById('container').innerHTML = html;
p { margin-left: 20px; }
<div id="container"></div>