Javascript group objects by property [closed]
I'm trying to group objects in an array by date:
var list = [
{
date: "2017-01-01",
type: "type1",
amount: 100
},
{
date: "2017-01-01",
type: "type2",
amount: 150
},
{
date: "2017-01-02",
type: "type1",
amount: 200
}
]
And I'm trying to get something like:
var dateArr = [
{
date: "2017-01-01",
activities: [
{
type: "type1",
amount: 100
},
{
type: "type2",
amount: 150
}]
}
]
I have tried a few things...like this using underscore (from here https://stackoverflow.com/a/15888912/4989305):
var dateArr = _
.chain(list)
.groupBy('date')
.map(function(value, key) {
return {
date: key,
activities: [{
type: _.pluck(value, 'type'),
amount: _.pluck(value, 'amount')
}]
}
})
.value();
I've also tried this (from here https://stackoverflow.com/a/31373860/4989305)
var dateArr = {};
list.forEach(function(item){
dateArr[item.date] = dateArr[item.date]||[];
dateArr[item.date].push(item);
});
But, for some reason both return empty.
Any help will be greatly appreciated.
A few lines of modern JavaScript will get you the result you want:
var dateArr = Object.values(list.reduce((result, {
date,
type,
amount
}) => {
// Create new group
if (!result[date]) result[date] = {
date,
activities: []
};
// Append to group
result[date].activities.push({
type,
amount
});
return result;
}, {}));
Explaination:
- Use
Array.reduce
to consolidate the list into a set of results, a plain object, grouped by date. - The consolidate function destructure the item into three parameters.
- It then creates a new group if necessary.
- Current item's type and amount is then pushed to the group as part of an object literal.
- The same set is returned to the
reduce
, so that the next item will consolidate into the same set. - Use
Object.values
to extract the values from the set. (Drop the keys)
You could use a hash table for groupiung by date and assign the single group to the result array.
var list = [{ date: "2017-01-01", type: "type1", amount: 100 }, { date: "2017-01-01", type: "type2", amount: 150 }, { date: "2017-01-02", type: "type1", amount: 200 }],
result = [];
list.forEach(function (hash) {
return function (a) {
if (!hash[a.date]) {
hash[a.date] = { date: a.date, activities: []};
result.push(hash[a.date]);
}
hash[a.date].activities.push({ type: a.type, amount: a.amount });
};
}(Object.create(null)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I hope this is what you exactly need.
var list = [
{
date: "2017-01-01",
type: "type1",
amount: 100
},
{
date: "2017-01-01",
type: "type2",
amount: 150
},
{
date: "2017-01-02",
type: "type1",
amount: 200
}
]
var dateArrKeyHolder = [];
var dateArr = [];
list.forEach(function(item){
dateArrKeyHolder[item.date] = dateArrKeyHolder[item.date]||{};
var obj = dateArrKeyHolder[item.date];
if(Object.keys(obj).length == 0)
dateArr.push(obj);
obj.date = item.date;
obj.activities = obj.activities || [];
obj.activities.push({type:item.type, amount: item.amount });
});
console.log(JSON.stringify(dateArr));