Gary
Gary

Reputation: 273

JavaScript - Grouping items into arrays

I have a JavaScript array that is something like this:

var items = [
 { id:1, group:'Produce', name:'Apple', weight: 0.5 },
 { id:2, group:'Produce', name:'Banana', weight: 0.2 },
 { id:3, group:'Meat', name:'Beef', weight: 1.0 },
 { id:4, group:'Meat', name:'Chicken', weight: 0.75 },
 { id:5, group:'Dairy', name:'Milk', weight:1.0 }
];

I want to look through this array and dynamically put them in arrays by their group. I tried the following, however, it didn't work:

var groups = [];
for (var i = 0; i<items.length; i++) {
  var groupName = items[i].group;
  if (groups.includes(groupName) === false) {
    groups[groupName] = new Array();
  }
  groups[groupName].push(items[i]);
}

Basically, I'm trying to create a Hashtable in JavaScript. The key is the group name and the value is an Array of items in that group. However, I've been unsuccessful. What am I missing here?

Thank you so much for your help!

Upvotes: 1

Views: 64

Answers (5)

Tremmillicious
Tremmillicious

Reputation: 506

I alwasy use lodash or underscore

But however, try this using reduce function

 var items = [
   { id:1, group:'Produce', name:'Apple', weight: 0.5 },
     { id:2, group:'Produce', name:'Banana', weight: 0.2 },
     { id:3, group:'Meat', name:'Beef', weight: 1.0 },
     { id:4, group:'Meat', name:'Chicken', weight: 0.75 },
     { id:5, group:'Dairy', name:'Milk', weight:1.0 }
 ];

 Array.prototype.groupDynamically = function(prop) {
   return this.reduce(function(groups, item) {
     var val = item[prop];
     groups[val] = groups[val] || [];
     groups[val].push(item);
     return groups;
   }, {});
 }

 //Then in your case say

var groups = items.groupDynamically('group');

Upvotes: 0

chrisbajorin
chrisbajorin

Reputation: 6153

Another alternative is to use reduce:

var items = [
 { id:1, group:'Produce', name:'Apple', weight: 0.5 },
 { id:2, group:'Produce', name:'Banana', weight: 0.2 },
 { id:3, group:'Meat', name:'Beef', weight: 1.0 },
 { id:4, group:'Meat', name:'Chicken', weight: 0.75 },
 { id:5, group:'Dairy', name:'Milk', weight:1.0 }
];

const grouped = items.reduce((accum, item) => {
	accum[item.group] = accum[item.group] ? accum[item.group].concat(item) : [item];
	return accum;
}, {});

console.log(grouped);

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386883

You could use just an object and check if the key exist. If not take a new array.

var items = [{ id: 1, group: 'Produce', name: 'Apple', weight: 0.5 }, { id: 2, group: 'Produce', name: 'Banana', weight: 0.2 }, { id: 3, group: 'Meat', name: 'Beef', weight: 1.0 }, { id: 4, group: 'Meat', name: 'Chicken', weight: 0.75 }, { id: 5, group: 'Dairy', name: 'Milk', weight:1.0 }],
    groups = Object.create(null),          // take a really empty object
    groupName,
    i;
    
for (i = 0; i < items.length; i++) {
    groupName = items[i].group;
    if (!groups[groupName]) {              // check if the key in object exists
        groups[groupName] = [];            // if not, assign an empty array
    }
    groups[groupName].push(items[i]);
}

console.log(groups);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

kind user
kind user

Reputation: 41913

I would suggest you following simple solution.

var items = [
 { id:1, group:'Produce', name:'Apple', weight: 0.5 },
 { id:2, group:'Produce', name:'Banana', weight: 0.2 },
 { id:3, group:'Meat', name:'Beef', weight: 1.0 },
 { id:4, group:'Meat', name:'Chicken', weight: 0.75 },
 { id:5, group:'Dairy', name:'Milk', weight:1.0 }
], obj = {};

items.forEach(c => (obj[c.group] || (obj[c.group] = [])).push(c));

console.log(obj);

Upvotes: 1

Yoann
Yoann

Reputation: 3070

Your groups should be an object.

Then you're testing groups.includes(groupName) but it is an array function, and you're creating an hashtable.

Instead, check if the key exists on the object with groups[groupName] === undefined.

var groups = {};
for (var i = 0; i<items.length; i++) {
  var groupName = items[i].group;
  if (groups[groupName] === undefined) {
    groups[groupName] = new Array();
  }
  groups[groupName].push(items[i]);
}

Upvotes: 0

Related Questions