Transforming the api response object into a map containing nested maps with string values

Is there a way to optimize the code below without using loops? Although I prefer not to use loops in my code, the current implementation relies on them. I'm curious if achieving the same result is possible with a different approach.

Code:

ts

private getData(): Observable<any> {
   return this.httpService.get(this.urlConfig.someUrl).pipe(
     map(res => {
       let x = this.recurseMap(res);
     })
   );
 }

 private recurseMap(obj): Map<string, any> {
  const m = new Map<string, any>();
  for (let key in obj) {
     if (typeof obj[key] === 'object') {
      obj[key] = this.recurseMap(obj[key]);
    }
    m.set(key, obj[key]);
  }
  return m;
}

The response for

this.httpService.get(this.urlConfig.someUrl)
will be

{
  "Obj1": {
    "1": "A",
    "2": "B",
    "4": "C",
    "8": "D",
    "16": "E",
    "32": "F",
    "64": "G"
  },
  "Obj2": {
    "0": "H",
    "1": "I",
    "2": "J",
    "3": "K"
  },
  "Obj3": {
    "0": "L",
    "1": "M"
  }
}

The resulting x would hold values like this (map<string,map<string,string>>)

{
  key: "Obj1",
  value: [
    { key: "1", value: "A" },
    { key: "2", value: "B" },
    { key: "4", value: "C" },
    ...
  ]
}

Answer №1

If you're looking for a solution, consider using either loops or recursive functions. However, using both may not be necessary if you prefer to avoid explicit loop usage.

Before diving into the code, keep in mind that your desired outcome should be an array. Having the same key name can lead to the last key overriding all previous ones, so it's advisable to have an array of maps instead.

Another point to note is that altering the function argument at this line

obj[key] = this.recurseMap(obj[key]);
may not be required. This function is meant to map and not transform the input argument.

If you want to avoid explicitly using loops, you can try the following approach:

function rmap(obj) {
    return Object.keys(obj).map(key => {
        let m = new Map();
        if(typeof obj[key] === 'object') {
            return m.set(key, rmap(obj[key]));
        }
        return m.set(key, obj[key]);
    })
}

Alternatively, consider this version without utilizing Map:

function rmap(obj) {
    return Object.keys(obj).map(key => {
        if(typeof obj[key] === 'object') {
            return {key: key, value: rmap(obj[key])};
        } else {
            return {key: key, value: obj[key]}
        }
    })
}

Keep in mind that Object.keys(..).map internally uses a loop, but you don't need to directly handle it.

I hope this provides some assistance :)

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

Angular with Firebase: How to ignore a field in a query

I am curious to see if my current structure is compatible with Firebase, or if I need to make adjustments. Let's take a look at an example using the "/rooms" endpoint, which contains an array of Room objects: export class Room { id: number; p ...

Struggled with setting up the WebSocket structure in typescript

Issue Running the code below results in an error: index.tsx import WebSocket from 'ws'; export default function Home() { const socket = new WebSocket('ws://localhost:1919/ws'); return ( <div>Home</div> ); } ...

Error: The unit test encountered an issue as it is unable to access the property 'subscribe' of an undefined value

I'm currently troubleshooting the "should create" unit test for a component, and I keep running into this error: TypeError: Cannot read property 'subscribe' of undefined at ElectionResultsChartsComponent.webpackJsonp../src/app/pages/use ...

What is the reason for `downlevelIteration` not being enabled by default?

When directing towards ES5 and using the spread operator ... to convert an Iterator to an Array, it prompts the need for the -downlevelIteration compiler option. Enabling this option allows the spread operators to function without any errors. I'm cur ...

How to determine the presence of 'document' in Typecsript and NextJS

Incorporating NextJS means some server-side code rendering, which I can manage. However, I'm facing a challenge when trying to check for set cookies. I attempted: !!document && !!document.cookie as well as document !== undefined && ...

Ensuring the type safety of arguments in TypeScript through conditional checking based on the previous argument

I am looking to implement type-checking for function arguments, where the properties of the second argument are based on the properties of the previous one. The config variable should only contain properties present in objects within the values array. The ...

Access the data within a jsonArray using Cypress

I'm dealing with a test.json file that contains a jsonArray [{ "EMAIL": "email_1", "FIRST_NAME": "Daniel" }, [{ "EMAIL": "email_2", "FIRST_NAME": "John" }] ] I'm trying to figure out how to use cypre ...

Error in MEAN Stack: Unable to access the property 'companyTitle' because it is undefined

I have established a MongoDB collection named joblist in my database. Additionally, I have developed a DB schema known as jobList.js. var mongoose = require('mongoose'); const joblistSchema = mongoose.Schema({ companyTitle: String, jobT ...

Exploring end-to-end testing with NestJS and Guards

I'm trying to test an endpoint called /users using nestjs, but I encountered some errors. I'm unsure how to fix the issues and make the test pass with a guard. First Issue Nest is unable to resolve dependencies of the UserModel (?). Please en ...

What are the steps to conduct a vulnerability scan on an Angular/Node application?

I'm in the process of setting up a vulnerability check for my Angular 7/Node project. Can anyone advise on how to effectively run this type of process? Are there any recommended tools available? Initially, I attempted to use the dependency-check-mave ...

Angular 8 and the conundrum of date parsing issues

const timestamp = '2020-07-11T00:05:00'; const dateOfFlight = new Date(timestamp); dateOfFlight.getMonth() // The output should be 6 However, it is expected to be 7 based on the provided timestamp. ...

Angular + Ionic 4 - Converting String Interpolation to JSON String

I am working with a JSON object that looks like this: { "commands": [ { "command":"begin ${{password}}", "name":"Initialization", "description":"Send SMS begin+password" } ] } How can I dynamically pass data to ${{password}} ...

Unit testing in Angular 4 with Jasmine Spy: The expectation was for 'New text' but received undefined

I have a simple function in my app.component.ts that is meant to modify a parameter, and I am trying to test this function using a spy. However, for some reason, my changeText function always returns undefined. Can you help me identify what I might be doin ...

The element's type is implicitly set to 'any' as the expression of type 'string' is unable to index the 'PointDto' type

Comparing the values of x1, y1 and z1 in PointDto objects (point1 and point2) Example :- point1 => PointDto: { x1: "1.000000", y1: "1.0", z1: undefined pointIndex: 0, } point2 =& ...

Strategies for resolving the TypeScript error code TS7009?

I am currently new to Typescript programming and in the learning phase. I encountered a problem while coding and received an error in the backend console. Here is the code snippet that caused the error: function employee(id:number,name:string) { this.i ...

Failure to trigger the callback for mongoose.connection.once('open') event

Currently, I am in the process of setting up a custom Node server using Next.js. Although I'm utilizing Next.js this time around, it should not affect the outcome. In my previous applications, I always relied on mongoose.connection.once('open&ap ...

Tips for declaring a dynamically sized array in Typescript?

Is there a way to create an array structure where the first element is always a number and the following elements are always strings, with a minimum length of 1? This is my current approach: type MyArray = | [number] | [number, string] | [number, s ...

Instructions for creating a cutout on a doughnut chart using ng2-charts

Can someone help me with setting configuration options on my doughnut chart using ng2-charts? Specifically, I am trying to set the cutout property on the chart. Despite going through the documentation for charts-js and ng2-charts, I haven't been able ...

Ways to integrate user input into the header of an Angular HTTP post method

I need help figuring out how to incorporate user input into the header of a post method I am working with. I understand that some kind of binding is necessary, but I'm struggling to implement it in this case. Currently, I have a variable called postDa ...

What is the correct way to write a for loop in Angular/JavaScript to initialize a form?

I am working on a form and I am trying to create a loop based on the size of my matches array: pronoPlayer0:['',Validators.required] pronoPlayer1:['',Validators.required] pronoPlayer2:['',Validators.required] I am unsure o ...