Reputation: 143
I am new in JavaScript and programming. I get data via AJAX. I want to re-generate it to get a nested object grouped by part of the data. In this case I want it grouped by year
and month
Here is my data and my function:
myObj = [
{"date":'2019-06-05',"name":"abc 0"},
{"date":'2019-06-01',"name":"abc 1"},
{"date":'2019-05-25',"name":"abc 2"},
{"date":'2019-05-15',"name":"abc 3"},
{"date":'2020-06-30',"name":"abc 4"},
{"date":'2020-06-25',"name":"abc 5"},
{"date":'2020-05-28',"name":"abc 6"},
{"date":'2020-05-26',"name":"abc 7"}
];
function regenerate(data) {
var result = {
"allyears": [{}]
};
for (x = 0; x < data.length; x++) {
var year = data[x].date.slice(0, 4);
var month = data[x].date.slice(5, 7);
if (!result.allyears.months) {
result.allyears['year'] = year;
result.allyears.months = [{}];
}
if (!result.allyears.months.data) {
result.allyears.months['month'] = month;
result.allyears.months.data = [{}];
}
result.allyears.months.data[x] = data[x];
}
console.log(result);
return result;
};
regenerate(myObj);
Result I expect:
{
"allyears": [{
"year": "2019",
"months": [{
"month": "06",
"data": [{
"date": '2019-06-05',
"name": "abc 0"
},
{
"date": '2019-06-01',
"name": "abc 1"
}
]
}, {
"month": "05",
"data": [{
"date": '2019-05-25',
"name": "abc 2"
},
{
"date": '2019-05-15',
"name": "abc 3"
},
]
}]
}]
};
What am I missing in my function?
Upvotes: 1
Views: 205
Reputation: 7446
Probably not the cleverest solution, but it should do the job "beautifully".
The routine is taking the advantage of Array.reduce
, where an initial accumulator (in this case an empty array) is used and, while looping the original myObj
array, it checks whether:
I will add some comments to the snippet below for further explanations, the output, to me, seems okay.
const myObj = [
{"date":'2019-06-05',"name":"abc 0"},
{"date":'2019-06-01',"name":"abc 1"},
{"date":'2019-05-25',"name":"abc 2"},
{"date":'2019-05-15',"name":"abc 3"},
{"date":'2020-06-30',"name":"abc 4"},
{"date":'2020-06-25',"name":"abc 5"},
{"date":'2020-05-28',"name":"abc 6"},
{"date":'2020-05-26',"name":"abc 7"}
];
let res = {
allyears: myObj.reduce((acc, next) => {
let [year, month, day] = next.date.split('-');
// ^-- Acquire year, month and day (actually, day is not needed) from the original date string.
let yearRef = acc.find(i => i.year === year);
// ^-- checks whether the current year already exists in the array.
if (!yearRef) acc.push({year}), yearRef = acc[acc.length - 1];
// ^-- if it doesn't, it creates it and fill the above reference of it.
yearRef.months = yearRef.months || [];
// ^-- same as the year above, but with month.
let monthRef = yearRef.months.find(i => i.month === month);
if (!monthRef) yearRef.months.push({month}), monthRef = yearRef.months[yearRef.months.length - 1]// ^-- same as above, with month.
monthRef.data = (monthRef.data || []).concat(next);
// ^-- once the month element is available, add the next element to data. If data does not yet exist, init it.
return acc;
}, [])
};
console.log(res);
Upvotes: 1