Iterate through an array containing objects that may have optional properties, ensuring to loop through the entire

I need help iterating through an array of objects with a specific interface structure:

export interface Incident {
  ID: string;
  userName1?: string;
  userName2?: string;
  userPhoneNumber?: string;
  crashSeverity: number;
  crashTime: number;
}

Here is a sample data set:

  {
    crashID: "CO111111",
    userName1: "TEST",
    userName2: "NAME2",
    userPhoneNumber: "11111",
    crashSeverity: 2,
    crashTime: 1571566666
  },
  {
    crashID: "12345",
    userName1: "TEST",
    crashSeverity: 2,
    crashTime: 1571566666
  }

I want to save this data to a csv file, but I'm struggling with iterating through the entire incident interface for each object and handling missing properties. Is there a way to achieve this?

An example output can be seen here: https://i.sstatic.net/ByAHg.png

This is my current code snippet:


  ConvertToCSV(objArray) {
    const array =
      typeof objArray !== "object" ? JSON.parse(objArray) : objArray;
    let str = "";
    let header = "";

    for (const index in objArray[0]) {
      header += index + ";";
    }
    header = header.slice(0, -1);
    // append Label row with line break
    str += header + "\r\n";

    // loop through every entry
    for (let i = 0; i < array.length; i++) {
      let line = "";
      // loop through every row
      for (const firstIndex in array[i]) {
          line += array[i][firstIndex] + ";";
      }
      str += line + "\r\n";
    }
    return str;
  }

Answer №1

Interfaces are only present during compile time and do not exist at run-time, making it impossible to inspect them using code.

However, there are ways to ensure that the output CSV is properly formatted by examining the data and organizing the fields correctly. This involves analyzing all the data to determine which fields are used and creating a logical order for them. This process is similar to performing a topological sort.

The provided code accomplishes this task by first scanning and ordering the data, then encoding it into a CSV format. The function `convertToCSV` parses the object array, identifies field dependencies, performs a topological sort of the fields, and generates the CSV data accordingly.

This script demonstrates how to efficiently convert structured data into a well-organized CSV output:

function convertToCSV(objArray) {
    const array =
        typeof objArray === "string" ? JSON.parse(objArray) : objArray;
    
    // Iterate the whole array to find any fields
    //    Keep track of which fields have to precede other fields
    const predecessors = new Map;
    for (const obj of array) {
        Object.keys(obj).forEach((key, i, keys) => {
            if (!predecessors.has(key)) predecessors.set(key, new Set);
            if (i) predecessors.get(key).add(keys[i-1]);
        });
    }
    // Sort fields
    const fields = topologicalSort(predecessors);

    return [fields.join(";"), // header line
        ...array.map(obj => fields.map(field => obj[field] || "").join(";")) // data lines
    ].join("\r\n");
}

function topologicalSort(predecessors) {
    const visited = new Set;
    
    function visit(key) {
        if (visited.has(key)) return;
        predecessors.get(key).forEach(visit);
        visited.add(key);
    }
    
    for (let key of predecessors.keys()) visit(key);
    return [...visited];
}

// Sample data
const data = [{
    userName2: "NAME2",
    userPhoneNumber: "11111",
    crashSeverity: 2,
  }, {
    userName1: "TEST",
    crashSeverity: 2,
    crashTime: 1571577777
  }, {
    crashID: "12345",
    userName1: "Mr First",
    userName2: "Second name",
    crashSeverity: 3,
    crashTime: 1571588888
  }];

const csv = convertToCSV(data);
console.log(csv);

Answer №2

To tackle this issue, I implemented a method where I saved the headers within the .ts file and retrieved the values by referencing their respective header names:

headers = [
  "crashID",
  "userName1",
  "userName2",
  "userPhoneNumber",
  "crashSeverity",
  "crashTime"
];

convertToCSV(objArray) {
  const array =
    typeof objArray !== "object" ? JSON.parse(objArray) : objArray;
  let str = "";
  const header = this.headers.join(";");
  str += header + "\r\n";

  // iterate through each entry
  for (let i = 0; i < array.length; i++) {
    let line = "";
    // iterate through each row
    for (const headerElem of this.headers) {
      line += array[i][headerElem];
      line += ";";
    }
    str += line + "\r\n";
  }
  return str;
}

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

Effective ways to manage extensive forms in Angular 2

I have a complex form in my application. What is the most effective way to collect data from this form and transmit it to the API using Angular 5? ...

Remove any javascript code from the ajax modal when it is closed or hidden

I am in the process of creating a music website that showcases songs along with their lyrics. One of the features I have added is a lyrics button that, when clicked while a song is playing, opens up a modal displaying the live lyrics. Everything works per ...

Utilizing span elements to display error messages

Currently, I am using a directive on a field to prevent users from entering HTML tags and JavaScript events. However, I am encountering a few challenges: a) My goal is to display an error message immediately when a user tries to input HTML tags or JavaScr ...

Error Type: TypeError when using Mongoose's FindOneAndUpdate function

I am encountering difficulties while trying to implement a findOneAndUpdate query. //UserController UserDAO ['findOneAndUpdate'](userId, {& ...

What is the best way to retrieve seat number upon clicking in React Native?

I have implemented a for loop and assigned its value in the click function to retrieve the seat number when a seat is clicked. However, I am only getting the last number of the for loop every time a seat is clicked. Can someone guide me on how to obtain th ...

a new approach for creating a conditional function in pointfree fashion

Can someone help me convert this code into a pointfree style? To provide context: The function receives an Array of Either types and returns a Task type. If any of the Either types have the left set, the Task type is rejected with that value. If none of t ...

Is hard coding permissions in the frontend considered an effective approach?

I'm in the process of creating an inventory management system that allows admin users to adjust permissions for other employees. Some permissions rely on others to function properly, and I need to display different names for certain permissions on the ...

Regular expressions: understanding greedy versus lazy quantifiers

Imagine this situation: a = 'one\\two\\three.txt'; The desired output is "three.txt". However, the attempted solution of: a.match(/\\(.+?)$/) is unsuccessful. What could be causing this issue? How can we successf ...

Retrieve the input field's value with Selenium, verify its accuracy, and proceed to log a message to the console

Hey there! I'm facing a challenge while working with Selenium Webdriver, specifically Chrome Webdriver and writing tests in JavaScript. The problem is in a section of the code where I can't seem to grab the value typed into an input field using t ...

Running a script upon service initialization

Can code be run when a service is first initialized? For instance, if the product Service is being initialized, I'd like to execute the following code: this.var = this.sharedService.aVar; ...

Examining a feature by solely utilizing stubs

I've been immersed in writing tests for the past few weeks. In my workplace, we utilize Mocha as our test runner and Chai for assertions, with Sinon for creating stubs. However, there's a recurring issue that's been bothering me. I've w ...

Angular 2: The window.crypto.subtle.importKey function functions properly on 'localhost' but encounters issues on an 'ip' address

As a newcomer to Angular 2, I am working on creating a login form that encrypts and sends the user's emailid and password to the server. I have successfully implemented AES-ECB using AES-CTR from the following link: https://github.com/diafygi/webcry ...

Tips for handling the rejection of a promise within a callback function in Node.js

How can we effectively incorporate a catch statement within a rejectionCallback function of a promise? Is it feasible or advisable to structure the code in this manner? Would the Promise object need to be passed into the rejection function in such a scena ...

Populate a Textbox Automatically using a Dropdown List

MVC 4 Changing multiple display fields based on DropDownListFor selection Having some issues trying to implement the solution mentioned above. It seems like there might be a problem with either my javascript code or the controller. JavaScript in View ...

Removing sourceMappingURL from an Angular Universal build: A step-by-step guide

Using this repository as my foundation, I have successfully resolved most of the plugin errors except for one that continues to elude me. It's puzzling because no other plugin anticipates a .map file in an SSR build since it is intended for productio ...

Tips for showing images with the full path URL retrieved from JSON using AngularJS

I am currently working on a project that involves displaying images from a JSON file. The URLs of these images are stored in the JSON file. Currently, my code is only outputting the URLs themselves, which is expected. However, I am looking for a way to act ...

Troubleshooting: Why are my Angular 8 Carousel Slide Animations not functioning

Looking to create a carousel slideshow with images sliding from right to left and smoothly transition to the next image. All the necessary code can be found in this STACKBLITZ Here is the HTML snippet: <ngb-carousel *ngIf="images" [showNavigationArro ...

Missing sidebar display

Hi there! I am having an issue with my sidebar not appearing correctly when I click on the toggle button. It seems to be moving to the side, but the sidebar itself is blank or transparent. I suspect that the problem lies within my JavaScript file. As a beg ...

Using strings "true/false/null" in React Map render instead of true/false/null values

Imagine working in React, where I am looping through JSON data stored in the state variable this.state.searchData. Some of the data values returned from the API call may include true, false, or null. Here is an example: "active": true, "partition": n ...

According to Intelijj IDEA, the success function in the AJAX request is reported as unused

I've encountered an issue and I'm unsure of the cause. This is my code for testing AJAX requests: function sendAJAX() { var dataToSend = {}; dataToSend["username"] = $("#username").val(); dataToSend["age"] = $("#age").val(); data ...