Home > other >  Problem with grouping array of objects in JS
Problem with grouping array of objects in JS

Time:11-09

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'));

CodePudding user response:

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.

CodePudding user response:

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' ]
}

CodePudding user response:

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"
        }
    ]
}

CodePudding user response:

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>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related