Building Hash by grouping array of objects based on a property of the items
Ruby has anticipated your need, and has got you covered with Enumerable#group_by
:
irb(main):001:0> aers = %w(a b c d ab bc de abc)
#=> ["a", "b", "c", "d", "ab", "bc", "de", "abc"]
irb(main):002:0> aers.group_by{ |s| s.size }
#=> {1=>["a", "b", "c", "d"], 2=>["ab", "bc", "de"], 3=>["abc"]}
In Ruby 1.9, you can make this even shorter with:
irb(main):003:0> aers.group_by(&:size)
#=> {1=>["a", "b", "c", "d"], 2=>["ab", "bc", "de"], 3=>["abc"]}
How to group objects in an array based on a common property into an array of arrays
Just take a hash table and group by year
and take the values from the hash table.
Bonus: A sorted result, because the keys of the object are sorted, if the keys could be read as indices of an array.
var films = [{ name: 'film 1', year: '1992' }, { name: 'film 2', year: '1992' }, { name: 'film 3', year: '1995' }, { name: 'film 4', year: '1995' }, { name: 'film 5', year: '1995' }, { name: 'film 6', year: '1998' }, { name: 'film 7', year: '1998' }], grouped = Object.values( films.reduce((r, o) => { (r[o.year] = r[o.year] || []).push(o); return r; }, {}) );
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
How can I group an array of objects by key?
Timo's answer is how I would do it. Simple _.groupBy
, and allow some duplications in the objects in the grouped structure.
However the OP also asked for the duplicate make
keys to be removed. If you wanted to go all the way:
var grouped = _.mapValues(_.groupBy(cars, 'make'),
clist => clist.map(car => _.omit(car, 'make')));
console.log(grouped);
Yields:
{ audi:
[ { model: 'r8', year: '2012' },
{ model: 'rs5', year: '2013' } ],
ford:
[ { model: 'mustang', year: '2012' },
{ model: 'fusion', year: '2015' } ],
kia:
[ { model: 'optima', year: '2012' } ]
}
If you wanted to do this using Underscore.js, note that its version of _.mapValues
is called _.mapObject
.
Group objects by multiple properties in array then sum up their values
Use Array#reduce with a helper object to group similar objects. For each object, check if the combined shape
and color
exists in the helper. If it doesn't, add to the helper using Object#assign to create a copy of the object, and push to the array. If it does, add it's values to used
and instances
.
var arr = [{"shape":"square","color":"red","used":1,"instances":1},{"shape":"square","color":"red","used":2,"instances":1},{"shape":"circle","color":"blue","used":0,"instances":0},{"shape":"square","color":"blue","used":4,"instances":4},{"shape":"circle","color":"red","used":1,"instances":1},{"shape":"circle","color":"red","used":1,"instances":0},{"shape":"square","color":"blue","used":4,"instances":5},{"shape":"square","color":"red","used":2,"instances":1}];
var helper = {};var result = arr.reduce(function(r, o) { var key = o.shape + '-' + o.color; if(!helper[key]) { helper[key] = Object.assign({}, o); // create a copy of o r.push(helper[key]); } else { helper[key].used += o.used; helper[key].instances += o.instances; }
return r;}, []);
console.log(result);
Most efficient method to groupby on an array of objects
If you want to avoid external libraries, you can concisely implement a vanilla version of groupBy()
like so:
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
console.log(groupBy(['one', 'two', 'three'], 'length'));
// => {"3": ["one", "two"], "5": ["three"]}
Group array of javascript objects based on value into there own sub array of objects
You could use a closure over a hash table for the same email address and their items.
var data = [{ email: "alex@test.com", fn: "Alex", sn: "McPherson", phone: "01233xxxxx", hours: "40", rate: "20", amount: "200", vat: "60", agency: "test", start: "08/06/2017", end: "10/06/2017" }, { email: "mike@test.com", fn: "Mike", sn: "Mann", phone: "01233xxxxx", hours: "50", rate: "70", amount: "500", vat: "90", agency: "test", start: "08/06/2017", end: "10/06/2017" }, { email: "fred@test.com", fn: "Fred", sn: "Frogg", phone: "01233xxxxx", hours: "80", rate: "90", amount: "800", vat: "100", agency: "test", start: "08/06/2017", end: "10/06/2017" }, { email: "alex@test.com", fn: "Alex", sn: "McPherson", phone: "01233xxxxx", hours: "90", rate: "30", amount: "900", vat: "120", agency: "test", start: "08/06/2017", end: "10/06/2017" }], result = data.reduce(function (hash) { return function (r, o) { if (!hash[o.email]) { hash[o.email] = []; r.push(hash[o.email]); } hash[o.email].push(o) return r; }; }(Object.create(null)), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
javascript - grouping objects by properties
You could group the items and the concat all groups in a single array.
It works by generating an object with the group as property an the items as items in the array.
In the next step, the object's values are taken and a new array is generated by concatination of the items with
Array#reduce
.{ // hash
"Technical detals": [
{
name: "Display",
group: "Technical detals",
id: "60",
value: "4"
},
{
name: "OS",
group: "Technical detals",
id: "37",
value: "Apple iOS"
}
],
Manufacturer: [
{
name: "Manufacturer",
group: "Manufacturer",
id: "58",
value: "Apple"
}
]
}
var data = [{ name: "Display", group: "Technical detals", id: "60", value: "4" }, { name: "Manufacturer", group: "Manufacturer", id: "58", value: "Apple" }, { name: "OS", group: "Technical detals", id: "37", value: "Apple iOS" }], groups = Object.create(null), result = [];
data.forEach(function (a) { groups[a.group] = groups[a.group] || []; groups[a.group].push(a); });
result = Object.keys(groups).reduce(function (r, k) { return r.concat(groups[k]);}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
javascript | Object grouping
Try with something like this:
function groupBy(collection, property) {
var i = 0, val, index,
values = [], result = [];
for (; i < collection.length; i++) {
val = collection[i][property];
index = values.indexOf(val);
if (index > -1)
result[index].push(collection[i]);
else {
values.push(val);
result.push([collection[i]]);
}
}
return result;
}
var obj = groupBy(list, "group");
Keep in mind that Array.prototype.indexOf
isn't defined in IE8 and older, but there are common polyfills for that.
Related Topics
How to Properly Chain Custom Methods in Ruby
How to Get the File Extension from a Url
How to Store Enum as String to Database in Rails
Trying to Understand Use of Self.Method_Name VS. Classname.Method_Name in Ruby
Deleting the Current Session with Rack::Session::Cookie
Convert Hash to Openstruct Recursively
Rails Nested With_Option :If Used in Validation
Limiting Characters/Words in View - Ruby on Rails
Running Webrick Server in Background
Rails Activerecord Query Date Range
Import SASS Partial Over Http Instead of Filesystem
When and Where Do I Require Files in a Rails Application
Ruby, Using Regex to Find Something in Between Two Strings
Regex to Match Hashtags in a Sentence Using Ruby