0

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'));
qweeee
  • 63
  • 1
  • 2
  • 8
  • 1
    What is the problem? Didn’t you ask this yesterday? – Dave Newton Nov 09 '21 at 13:42
  • @DaveNewton, I just want to show categories in h2 tag and each product of category in p tag. I just cannot achieve it with my code :( – qweeee Nov 09 '21 at 13:43
  • Note that it seems like `groupBy([products], 'category')` has a typo and should be `groupBy(products, 'category')` since `products` is already an array. – Emile Bergeron Nov 09 '21 at 14:56

4 Answers4

0

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.

Domino987
  • 8,475
  • 2
  • 15
  • 38
0

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' ]
}
Nils Fahle
  • 126
  • 1
  • 8
0

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>
ProDec
  • 5,390
  • 1
  • 3
  • 12
  • 1
    The question is tagged with React, generating an HTML string would be considered a bad practice, though the logic would be similar. – Emile Bergeron Nov 09 '21 at 14:51
-1
var groupBy = function (xs, key) {
       return xs.reduce(function (rv, x) {

           (rv[x[key]] = rv[x[key]] || []).push(x);
           return rv;
       }, {});
   };

   const arrayData = [
       { 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(arrayData, 'category'));

result:

{
    "Fruit": [
        {
            "id": 1,
            "name": "Apple",
            "category": "Fruit"
        },
        {
            "id": 2,
            "name": "Melon",
            "category": "Fruit"
        }
    ],
    "Phone": [
        {
            "id": 3,
            "name": "iPhone",
            "category": "Phone"
        },
        {
            "id": 4,
            "name": "Samsung Galaxy Note 8",
            "category": "Phone"
        }
    ],
    "Entertainment": [
        {
            "id": 5,
            "name": "Playstation 5",
            "category": "Entertainment"
        }
    ]
}
MD. RAKIB HASAN
  • 3,670
  • 4
  • 22
  • 35