Changing the format of a data structure using JavaScript/TypeScript

Hey there, I have a rowdata that looks like this:

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"
    },
   .....

];

This row data serves as the structure for a table on my website. The information is retrieved from the backend and now needs to be converted into a different format for the website. The new format should follow this pattern:

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 transformation of the second data is solely based on the first data provided. If you have any ideas or suggestions on how I can achieve this in JavaScript as I am relatively new to it, please share. Thanks in advance!

Answer №1

Some of the TypeScript elements have been excluded from this snippet as they are not entirely relevant. The primary focus here is on the logic for parsing the ROWDATA variable. Take a look at the code snippet below with accompanying comments to help clarify its functionality.

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 ={}; // track seen times
ROWDATA.forEach(e => {
  const newClass = {
    class: e.class
    // more info can be added here
  }
  
  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 {
    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)

Answer №2

I'm unsure about which aspects of this project require dynamic elements, as it appears you are specifically selecting certain attributes and assigning names based on a predetermined pattern.

Nevertheless, if you wish to process your initial dataset through a function to generate the subsequent output, you can follow these steps:

let updatedData = 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(updatedData);

link:

Answer №3

Here's the resolution.

Apologies for using Ramda.js, but leveraging Ramda.js significantly reduced the volume of code required.

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/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1c6e7d71787d5c2c322e29322c">[email protected]</a>/dist/ramda.min.js"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

using v-model in multiple components

Is there a way to simplify this code? <b-address v-model:name="address.name" v-model:addressLine="address.addressLine" v-model:streetNumber="address.streetNumber" v-model:town="address.town" ...

Developing a method to handle HTTP errors when utilizing the fetch method to retrieve data from an API endpoint

// GitHub users document.getElementById('btn3').addEventListener('click', fetchData); // Fetching from external API function fetchData() { fetch('https://api.github.com/users') .then(function (res) { co ...

"Encountering issues with the React.js random name generator, resulting in either undefined outputs

I'm struggling with my code and need assistance. I'm trying to randomly select a name from an array named "names", but something seems to be incorrect in my implementation. The goal is to use getRandomName function to pick a random name from the ...

Unconventional login processes showcased in Redux-Saga's documentation

When looking at the login flow example in the redux-saga documentation, it is clear that the expected action sequence is well-defined. However, does the LOGOUT action always follow the LOGIN action? In real-world scenarios, such as when a user's sessi ...

Angular - Show user information on homepage post authentication

Utilizing Angular 7 and Laravel 5.8 for user Login implementation where Laravel serves the endpoint to Angular. The user login functionality has been successfully created, however, unsure about displaying the logged-in username. User.ts export class User ...

Is it possible for issues to arise when serving a web app using the "Globals" module in the Mean Stack?

Looking to transfer a variable (a constructed filename) from one file to another within an API can be quite challenging. One solution that comes to mind is utilizing globals, but with my current code structure, it seems like the only viable option. To addr ...

Creating a dynamic cascading dropdown list with Vue.js: Step-by-step guide

I successfully implemented a dropdown list using Vue.js, but now I want to add another similar list. How can I set this up? Here are the codes for both dropdown lists: var addUserVue = new Vue({ el: "#app", data: { heading: "Vue Select Cas ...

AngularJS's support for html5mode on GitHub pages is now available

Is it feasible for GitHub pages to accommodate AngularJS in html5mode? I came across a source online suggesting that it can be done with a fallback page for 404 errors. However, this solution seems flawed as it may result in multiple 404 errors, which wou ...

How can React Native on Android open another app?

I'm encountering an issue while attempting to open another app () from my own app. Despite numerous tutorials directing me to the Play Store only, I came across a GitHub link (https://github.com/FiberJW/react-native-app-link) that allows for app openi ...

The use of the `/deep/` combinator in CSS has been phased out and is set to be completely removed

After updating my angular to version 4.0.0 and chrome to 62.0.3202.94, I encountered the following error message: [Deprecation] /deep/ combinator in CSS is deprecated and will be removed in M63, around December 2017. Refer to for more information. The ...

How to pause a loop temporarily before proceeding with the next iteration

I am facing a challenge where I want to trigger two events simultaneously, but only one event should be allowed to continue at a time. If an event is already in progress, I need the ability to forcefully stop it and allow the other event to take control. S ...

I am unable to utilize autocomplete with types that are automatically generated by Prisma

Currently, I am working on a project utilizing Next and Prisma. Within my schema.prisma file, there are various models defined, such as the one shown below: model Barbershop { id String @id @default(uuid()) name String address String ...

Easy-to-use blog featuring Next.js 13 and app router - MDX or other options available

Currently in the process of transitioning a Gatsby website to Next.js (v13.4) and utilizing the new App Router. However, I'm facing some challenges when it comes to migrating the blog section over because there isn't much accurate guidance availa ...

What is the best way to navigate to the next video in my YouTube API search results with Vue.js?

After setting up a search component that sends data to the parent player.component, I pass the video id and an object containing 5 search results to the player.component. <template> <div class="mobile-screen"> <b-container> ...

Sending a Post Request from Express to MongoDB

My attempt to send information to MongoDB using Express is experiencing some issues. The GET request works fine, indicating that the database connections are functioning properly. Within my server.js file, I have defined a Schema: var todoSchema = new Sc ...

Adding together separate numbers within an array using JavaScript

I am currently working on a task that involves summing up all the numbers in each array and displaying the total sum of that specific array. Unfortunately, I am facing challenges in figuring out how to achieve this functionality through my code. For examp ...

Tips for performing an integration test on a material UI <Slider /> component using either userEvent or fireEvent

I'm facing some challenges while trying to perform an integration test on a material UI component. I can locate the slider element, but have not been successful in moving the slider and retrieving the new value. Can you provide any guidance on how to ...

There seems to be an issue with the hidden field value not being properly set within the

I created a function called getConvertionValue. Inside this function, I make an ajax call to the getCurrencyConvertion function in the controller. function getConvertionValue(from, to) { if (from != to) { $.ajax({ url: base_url + 'admin/o ...

Here's a guide on using a button to toggle the display of password value in Angular, allowing users to easily hide

I have successfully implemented an Angular Directive to toggle the visibility of password fields in a form. However, I am facing an issue with updating the text displayed on the button based on the state of the input field. Is there a way for me to dynami ...

Which is better: storing an element in a variable or selecting it every time it's needed for efficiency?

When targeting an element multiple times, which method is more efficient? Consider Example 1: var el = $("#element"); el.html("foo"); el.html("bar"); Compare it to Example 2: $("#element").html("foo"); $("#element").html("bar"); Is there a noticeable ...