Reputation: 33
Please bear with me, I'm a novice javascript developer with a sorting problem that I can't wrap my head around.
I'm retrieving an array of objects (JSON response) by an api like this:
var arr = [
{
"year": "2011",
"activity": "bowling"
},
{
"year": "2009",
"activity": "shopping",
},
{
"year": "2011",
"activity": "cooking"
},
{
"year": "2006",
"activity": "singing"
}
]
I have a function that removes all of the duplicate years (as intended), but I wish to take the 'activity' value of the duplicate object and add it to the activity value of that same year is left after removing duplicates
My function that removes the duplicate year is as follows
var new_arr = new_arr.reduce((unique, o) => {
if(!unique.some(obj => obj.year === o.year)) {
unique.push(o);
}
return unique;
},[]);
which leaves me with this
var arr = [
{
"year": "2011",
"activity": "bowling"
},
{
"year": "2009",
"activity": "shopping",
},
{
"year": "2006",
"activity": "singing"
}
]
What I wish to accomplish:
var arr = [
{
"year": "2011",
"activity": "bowling, cooking"
},
{
"year": "2009",
"activity": "shopping",
},
{
"year": "2006",
"activity": "singing"
}
]
JSFiddle: https://jsfiddle.net/4s1uaex0/2/
I feel like I'm almost there, but I don't know where to start from here. Can anyone point me into the right direction with a guide or example? Help would be greatly appreciated! Thank you
Upvotes: 3
Views: 70
Reputation: 7891
const inputArr = [
{
"year": "2011",
"activity": "bowling"
},
{
"year": "2009",
"activity": "shopping",
},
{
"year": "2011",
"activity": "cooking"
},
{
"year": "2006",
"activity": "singing"
}
];
const outputArr = inputArr.sort((objA, objB) => Number(objA.year) - Number(objB.year))
.reduce((accu, obj) => {
const len = accu.length;
if(len == 0 || accu[len-1].year !== obj.year) {
accu.push(obj);
} else {
accu[len-1].activity += ', ' + obj.activity;
}
return accu;
}, []);
console.log(outputArr);
Upvotes: 0
Reputation: 3386
you can simply use for loop
var mem = {};
for(var i = 0; i < arr.length; i++) {
var currentItem = arr[i];
var year = currentItem['year'];
var activity = currentItem['activity'];
if(!mem.hasOwnProperty(year)) {
mem[year] = { 'year' : year, "activity": []};
}
mem[year]['activity'].push(activity);
}
var final = Object.values(mem);
Upvotes: 1
Reputation: 23515
Instead of checking if the year already exists in your accumulator : Check and modify.
const arr = [{
year: '2011',
activity: 'bowling',
},
{
year: '2009',
activity: 'shopping',
},
{
year: '2011',
activity: 'cooking',
},
{
year: '2011',
activity: 'cooking',
},
{
year: '2006',
activity: 'singing',
},
];
const new_arr = arr.reduce((tmp, x) => {
// Already exist
const exist = tmp.find(y => y.year === x.year);
if (exist) {
// Only add not existing activities to avoid duplicates
if (exist.activity.indexOf(x.activity) === -1) {
exist.activity = `${exist.activity}, ${x.activity}`;
}
return tmp;
}
tmp.push(x);
return tmp;
}, []);
console.log(new_arr);
Upvotes: 0
Reputation: 370879
Try reduce
-ing the activity
to an array in the accumulator first, then join each activity
property by commas afterwards. You can achieve this with a single reduce
, which is O(N)
, a some
inside of it will make it O(N^2)
, which is not necessary and probably undesirable:
var arr = [
{
"year": "2011",
"activity": "bowling"
},
{
"year": "2009",
"activity": "shopping",
},
{
"year": "2011",
"activity": "cooking"
},
{
"year": "2006",
"activity": "singing"
}
];
const output = Object.values(
arr.reduce((a, { year, activity }) => {
if (!a[year]) a[year] = { year, activity: [] };
a[year].activity.push(activity);
return a;
}, {})
);
output.forEach((item) => {
item.activity = item.activity.join(', ');
});
console.log(output);
Upvotes: 0