Hi I have a rowdata as below:
export const ROWDATA: Array<any> = [
{
id: "1",
start_time: "9:00:00",
end_time: "9:30:00",
day_of_week: 'monday',
lesson: "Lesson ABC",
class: "Class ABC",
room: "room1",
education_grade_subject: "Physics",
staff: "Amanda Jeremy",
timetable: "class timetable",
modified_user: "admin",
modified: "2017-01-15",
created_user: "admin",
created: "2017-01-15"
},
{
id: "2",
start_time: "9:30:00",
end_time: "10:00:00",
day_of_week: 'monday',
lesson: "Lesson XYZ",
class: "Class ABC",
room: "room2",
education_grade_subject: "Chemistry",
staff: "Amanda Jeremy",
timetable: "class timetable",
modified_user: "admin",
modified: "2017-01-15",
created_user: "admin",
created: "2017-01-15"
},
.....
];
Basically its a row data structure for a table in my website. The row data i retrieved from my backend. Now I need to convert/transform this data into another format for my website. The new format need to be in following format:
export const DATA: Array<any> = [
{
time: "9:00",
monday: [
{
class: 'room1',
title: {field: "lesson", text:"Lesson ABC", class:"lessonABC-title"},
content: [
{field: "education_grade_subject", text: "Physics", class:"lessonABC-subject-class"},
{field: "staff", text: "Amanda Jeremy", class:"lessonABC-staff-class"},
{field: "room", text: "Room 01", class:"lessonABC-room-class"}
],
uid: "1"
}
]
},
{
time: "9:30",
monday: [
{class: 'room2',
title: {field: "lesson", text:"Lesson XYZ", class:"lessonXYZ-title"},
content: [
{field: "education_grade_subject", text: "Chemistry", class:"lessonXYZ-subject-class"},
{field: "staff", text: "Amanda Jeremy", class:"lessonXYZ-teacher-class"},
{field: "room", text: "Room 02", class:"lessonXYZ-room-class"}
],
uid: "2"
}
]
},
....
The second data or transformed purely based on the first data. How can I achieve this guys? Very new to JavaScript. Any idea guys? Thanks in advance
I've removed some of the typescript bits here because they are not really relevant, as I believe the main issue is the logic to parse your ROWDATA variable. Have a look at the code below, I've included some comments to explain how it works.
const ROWDATA = [
{
id: "1",
start_time: "9:00:00",
end_time: "9:30:00",
day_of_week: 'monday',
lesson: "Lesson ABC",
class: "Class ABC",
room: "room1",
education_grade_subject: "Physics",
staff: "Amanda Jeremy",
timetable: "class timetable",
modified_user: "admin",
modified: "2017-01-15",
created_user: "admin",
created: "2017-01-15"
},
{
id: "2",
start_time: "9:30:00",
end_time: "10:00:00",
day_of_week: 'monday',
lesson: "Lesson XYZ",
class: "Class ABC",
room: "room2",
education_grade_subject: "Chemistry",
staff: "Amanda Jeremy",
timetable: "class timetable",
modified_user: "admin",
modified: "2017-01-15",
created_user: "admin",
created: "2017-01-15"
},
];
const group = [];
const map ={}; // keep track of the time that we have seen
ROWDATA.forEach(e => {
// object to be inserted to the day array in each of the object containing
// time property
const newClass = {
class: e.class
// ... fill in the rest of info here...
}
// if time does not exist in map,
// create new entry
if (!map[e.start_time]) {
map[e.start_time] = true;
const newEntry = { time: e.start_time };
newEntry[e.day_of_week] = [];
newEntry[e.day_of_week].push(newClass);
group.push(newEntry);
} else {
// time already exist, find that object with corresponding time
// and push the new class to the respective day
group.map(e2 => {
if (e.start_time === e2.time) {
if (e2[e.day_of_week]) {
e2[e.day_of_week].push(newClass);
} else {
console.log('!!!')
e2[e.day_of_week] = [];
e2[e.day_of_week].push(newClass);
}
}
return e2;
});
}
});
console.log(group)
I'm not really sure what parts of this you need to be dynamic since to me it looks like you are hand-picking certain properties and naming some things based on an obvious pattern arbitrarily.
But anyways if you want to run your first data set through a function to get the second output, you can do this:
let newdata = ROWDATA.map(item => {
return {
time: item.start_time,
[item.day_of_week]: [{
class: item.room,
title: {
field: "lesson",
text: item.lesson,
class: "lesson"+item.lesson.substr(item.lesson.length-3)+"-title"
}
content: [{
field: "education_grade_subject",
text: item.education_grade_subject,
class:"lesson"+item.lesson.substr(item.lesson.length-3)+"-subject-class"
}, {
field: "staff",
text: item.staff,
class:"lesson"+item.lesson.substr(item.lesson.length-3)+"-staff-class"
}, {
field: "room",
text: item.room,
class:"lesson"+item.lesson.substr(item.lesson.length-3)+"-room-class"
}]
}],
uid: item.id
};
});
console.log(newdata);
Sorry that I'm uses Ramda.js but Ramda.js helped me reduce the amount of code.
const ROWDATA = [
{
"class": "Class ABC",
created: "2017-01-15",
created_user: "admin",
day_of_week: "monday",
education_grade_subject: "Physics",
end_time: "9:30:00",
id: "1",
lesson: "Lesson ABC",
modified: "2017-01-15",
modified_user: "admin",
room: "room1",
staff: "Amanda Jeremy",
start_time: "9:00:00",
timetable: "class timetable"
},
{
"class": "Class ABC",
created: "2017-01-15",
created_user: "admin",
day_of_week: "monday",
education_grade_subject: "Chemistry",
end_time: "10:00:00",
id: "2",
lesson: "Lesson XYZ",
modified: "2017-01-15",
modified_user: "admin",
room: "room2",
staff: "Amanda Jeremy",
start_time: "9:30:00",
timetable: "class timetable"
}
]
const formatRoom =
R.pipe(R.last, R.prepend("0"), R.takeLast(2), R.join(""), (n) => `Room ${n}`)
const makeClass = (classSuffix) =>
R.pipe(R.prop('lesson'), R.split(" "), R.last, (name) => `lesson${name}${classSuffix}`,)
const spec = {
class: R.prop('room'),
uid: R.prop('id'),
title: {
field: R.always('lesson'),
text: R.prop('lesson'),
class: makeClass("-title"),
},
content: [
{
field: R.always('education_grade_subject'),
text: R.prop('education_grade_subject'),
class: makeClass("-subject-class"),
},
{
field: R.always('staff'),
text: R.prop('staff'),
class: makeClass("-teacher-class"),
},
{
field: R.always('room'),
text: R.pipe(R.prop('room'), formatRoom),
class: makeClass("-room-class"),
},
],
}
const formatTime =
R.dropLast(3)
const transformData =
R.pipe(
R.groupBy(R.prop('start_time')),
R.map(R.groupBy(R.prop('day_of_week'))),
R.map(R.map(R.map(R.applySpec(spec)))),
R.toPairs,
R.map(([start_time, groupsByDay]) =>
R.assoc('time', formatTime(start_time), groupsByDay)),
)
console.log(transformData(ROWDATA))
<script src="//cdn.jsdelivr.net/npm/ramda@0.25.0/dist/ramda.min.js"></script>