I have an array of objects that have a format like this:
const program = [
{ id: '1', week: 1, day: 1, description: 'week 1 day 1', completed: true },
{ id: '2', week: 1, day: 2, description: 'week 1 day 2', completed: true },
{ id: '3', week: 1, day: 3, description: 'week 1, day 3', completed: true },
{ id: '4', week: 2, day: 1, description: 'week 2, day 1', completed: true },
{ id: '5', week: 2, day: 2, description: 'week 2 day 2', completed: false },
{ id: '6', week: 2, day: 3, description: 'week 2 day 3', completed: true },
{ id: '7', week: 3, day: 1, description: 'week 3, day 1', completed: false },
// ....
{ id: '89', week: 11, day: 9, description: 'week 11, day 9', completed: false },
// ...
];
and I want the output to look something like this:
const weekMap = {
1: [
{ id: '1', week: 1, day: 1, description: 'week 1 day 1', completed: true },
{ id: '2', week: 1, day: 2, description: 'week 1 day 2', completed: true },
{ id: '3', week: 1, day: 3, description: 'week 1, day 3', completed: true },
],
2: [
{ id: '4', week: 2, day: 1, description: 'week 2, day 1', completed: true },
{ id: '5', week: 2, day: 2, description: 'week 2 day 2', completed: false },
{ id: '6', week: 2, day: 3, description: 'week 2 day 3', completed: true },
],
3: [
{ id: '7', week: 3, day: 1, description: 'week 3, day 1', completed: false },
// ....
],
11: [
{ id: '89', week: 11, day: 9, description: 'week 11, day 9', completed: false },
// ....
],
};
So far what I've tried was .reduce
export const toWeekMap = (programSteps) =>
programSteps.reduce((acc, curr) => {
if (!acc[curr.week]) {
acc[curr.week] = [];
}
if (!acc[curr.week][curr.day]) {
acc[curr.week][curr.day] = [];
}
console.log(acc);
return acc[curr.week][curr.day].push(curr);
}, {});
Though this doesn't work and I'm not sure of any ways around it. The error I get is
Uncaught TypeError: Cannot create property '1' on number '1'
Obviously there's something very off with my logic... maybe I'm misunderstanding .reduce
?
CodePudding user response:
Hello you can try this :
export const toWeekMap = (programSteps) =>
programSteps.reduce((acc, curr) => {
(acc[curr.week] = acc[curr.week] || []).push(curr);
return acc;
}, {});
CodePudding user response:
The main mistake of your code is in this line:
return acc[curr.week][curr.day].push(curr);
This is the equivalent of saying:
const a = acc[curr.week][curr.day].push(curr);
return a;
a
will contain the return value of the push function, which is the new length of the array.
What you actually want to do is:
acc[curr.week][curr.day].push(curr);
return acc;
After that, you can fix your logic inside the reduce according to your needs. If I understood correctly what you want, this should do:
const program = [
{ id: '1', week: 1, day: 1, description: 'week 1 day 1', completed: true },
{ id: '2', week: 1, day: 2, description: 'week 1 day 2', completed: true },
{ id: '3', week: 1, day: 3, description: 'week 1, day 3', completed: true },
{ id: '4', week: 2, day: 1, description: 'week 2, day 1', completed: true },
{ id: '5', week: 2, day: 2, description: 'week 2 day 2', completed: false },
{ id: '6', week: 2, day: 3, description: 'week 2 day 3', completed: true },
{ id: '7', week: 3, day: 1, description: 'week 3, day 1', completed: false },
// ....
{ id: '89', week: 11, day: 9, description: 'week 11, day 9', completed: false },
// ...
];
const toWeekMap = (programSteps) =>
programSteps.reduce((acc, curr) => {
if (!acc[curr.week]) {
acc[curr.week] = [];
}
acc[curr.week].push(curr);
return acc;
}, {});
console.log(toWeekMap(program))
CodePudding user response:
The usage of the reduce
is good. However, the logic of building the desired object is flawed at one point. Here is the correction
export const toWeekMap = (programSteps) =>
programSteps.reduce((acc, curr) => {
if (!acc[curr.week]) {
acc[curr.week] = [];
}
acc[curr.week].push(curr); //<<<--- compare here
console.log(acc);
return acc[curr.week][curr.day].push(curr);
}, {});