Using the map function in JavaScript for recursive operations

I am faced with a map that visually represents a graph as follows:

Map(5) {
  1 => [ 2, 3 ],
  2 => [ 7, 8, 10 ],
  3 => [ 4 ],
  10 => [ 12 ],
  4 => [ 11 ]
}

In addition, there's this specific class designed to generate a rooted tree:

class RootedTree {
    constructor (data, ...descendants) {
      this.data = data;
      this.descendants = descendants;
    }
}

The main objective at hand is to convert the given graph into a rooted tree based on a chosen root. Taking the example where 1 serves as the root, the desired output would be:

const RT = (...args) => new RootedTree(...args) // for simplification 
// intended result:
RT(1, RT(2, RT(7), RT(8), RT(10, RT(12))), RT(3, RT(4, RT(11)), RT(5))

My current approach involves the following code snippet:

let local_descendants = []
const toRT  = (root, node_map) => {
    rt = new RootedTree(root)
    if (node_map.get(root) !== undefined){
        node_map.get(root).map((node) => toRT(node, node_map), local_descendants)
    } else {
        return null
    }

    return local_descendants
}

rt = new RootedTree(1, toRT(1, map))

However, upon execution, the toRT function appears to return an empty array. It seems like there might be some confusion regarding the handling of variables within the function. I'm currently stuck and looking for guidance on how to address this issue.

Answer №1

The response from Ajax seems satisfactory, but you mentioned that you have a Map and wish for that specific Map instance to be an input for the toRT function (great!).

Here is the corresponding code:

class RootedTree {
    constructor (data, ...descendants) {
        this.data = data;
        this.descendants = descendants;
    }
}

const toRT = (data, map) =>
    new RootedTree(data, ...map.get(data)?.map(child => toRT(child, map))??[]);

const map = new Map([[1,[2,3]],[2,[7,8,10]],[3,[4]],[10,[12]],[4,[11]]]);
const root = toRT(1, map);
console.log(root);

Explanation

Your familiarity with Map and spread syntax is evident from your question, so let's delve into this expression:

map.get(data)?.map(child => toRT(child, map))??[]

The optional chaining operator, denoted by ?., ensures that the .map() method is only invoked when map.get(data) returns a defined value. Otherwise, it will default to using undefined instead of the result from .map().

Iterating over the child values retrieved from the Map entry for data</code using <code>.map(), each value is processed through a call to toRT(child, map). This call generates instances of RootedTree, resulting in an array of such instances that serve as the descendants for the node being constructed for data.

The Nullish coalescing operator, symbolized by ??, transforms the undefined output (from map.get()) into an empty array. This guarantees that the spread operator functions correctly even in this scenario.

Therefore, the lower-level nodes are created first to provide the necessary descendants arguments for subsequent new RootedTree calls. Ultimately, the root node is constructed last.

Answer №2

With each iteration, an object of type RootedTree can be generated by passing the data as the root parameter and subsequent recursive calls as the descendants:

var t = {1:[ 2, 3 ], 2:[ 7, 8, 10 ], 3:[ 4 ], 10:[ 12 ], 4:[ 11 ]}
class RootedTree {
   constructor (data, ...descendants) {
     this.data = data;
     this.descendants = descendants;
   }
   display(){
      return this.descendants.length === 0 ? `RT(${this.data})` : `RT(${this.data}, ${this.descendants.map(x => x.display()).join(', ')})`
   }
}
function toRT(root = 1){
   return (new RootedTree(root, ...(root in t ? t[root] : []).map(toRT)))
}
console.log(toRT().display())

Result:

RT(1, RT(2, RT(7), RT(8), RT(10, RT(12))), RT(3, RT(4, RT(11))))

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

Looking for an angular split pane library that is built exclusively for AngularJS without any reliance on other frameworks?

Is there a split-pane library available that can enable me to display 2 tables on a screen and allow users to drag the divider in the middle to adjust the sizes of each table? I have come across libraries such as the shagstrom one that offer this function ...

Exploring a JavaScript object's array

Greetings, I am looking to develop a simple visual editor for my plugins. let x = { tag : "a", atts : { href : "/", class : "a", text:"link" }, com ...

Enable the ability to input a value of -1 by clicking on a button or link, but only allow it once (the first click) without needing to disable the button or

I am working with the following script: <script language=javascript> function process(v){ var value = parseInt(document.getElementById('v').value); value += v; document.getElementById('v').value = valu ...

The Checkbox handler in Material-UI component fails to update the state - Version 5.0

Hey everyone, I'm facing an issue with my "Checkbox" component in React. After clicking on it, the state doesn't update to 'true' as expected. The checkbox works visually in the DOM but the state remains 'false'. Can someone p ...

When querying a document, the Mongoose array is missing

When querying for documents with an array, I'm encountering an issue where the returned documents do not include the array. Below is my code: Query Code (async () => { const data = await Lesson.find({signed: {$exists: true}}); cons ...

Adjust slider value dynamically with jQuery

I am working on a UI slider that ranges from 0 million to 20000 million. My goal is to change the displayed value when it reaches 1000 to show '1 milliard', and at 20000 to show '20 milliard'. For instance, if the value is 1100 millio ...

"Upon clicking the login button, I encountered an issue with redirecting to the destination

I've been working on developing a login page using Angular framework. However, I'm facing an issue where I am unable to access the destination page after entering the login credentials. Below, you can find a snippet of the code from the login.com ...

Can someone help me figure out this lengthy React error coming from Material UI?

Issues encountered:X ERROR in ./src/Pages/Crypto_transactions.js 184:35-43 The export 'default' (imported as 'DataGrid') could not be found in '@material-ui/data-grid' (potential exports include: DATA_GRID_PROPTYPES, DEFAULT ...

Encountered an issue when attempting to retrieve live data from the Firestore database with code: 'ERR_HTTP_HEADERS_SENT'

I'm currently in the process of building an app and I must admit, I'm quite new to all of this. I managed to create a basic function to retrieve data from Firestore and it seems to be working fine for now. Take a look at the code below: async ge ...

The function Server.listeners is not recognized by the system

Currently, I am following a tutorial on websockets to understand how to incorporate Socket.IO into my Angular project. Despite meticulously adhering to the instructions provided, I encountered an error when attempting to run my websockets server project: ...

Changing the line height causes the bullet position to shift downwards

Here is a bullet list: <ol className="graphkregular mt-2" style={{ display: "listItem" }}> <li> <small>{popupData.content[0].split("\n").join("\n")}< ...

Updating the count property of an object using setState in React

I have an array of integers ranging from 0 to 6 as my input. My goal is to create an object that gives the count of each number in the array. edition = [6, 6, 6, 1, 1, 2]; const [groupedEdition, setGroupedEdition] = useState([{"0": 0, "1&quo ...

Manipulating Data in TypeScript: Creating a Mutated Copy of a List of Dictionaries

After going through multiple answers, it appears that there might be a logical error. However, I am struggling to find a solution for this issue. In TypeScript/JavaScript, I have two lists of dictionaries. One list is a copy of the other for tracking purp ...

Is the MongoDB Native Node Driver Explanation Faulty?

I am facing challenges in obtaining a clear explanation while using the native MongoDB driver for Node.js. Interestingly, everything works fine when I use the mongo shell. Could there be an issue with my syntax or is there something else that I might be mi ...

Retrieving iframe contents upon refreshing the page

I have been facing a challenge trying to extract data from a school portal's Peoplesoft page that contains an iframe element. The issue arises when I navigate within the portal, such as clicking on a button to search for classes, causing changes in th ...

Display a loading dialog when an AJAX request is made

I am working on a Grails application and I would like to implement a visual indicator, such as a modal dialog, to show when an AJAX request is in progress. Currently, I rely on JQuery for all my AJAX requests. While they are triggered using Grails tags at ...

How to dynamically apply component-specific CSS in NextJS based on conditions

I'm working on my nextjs project and encountered an issue with adding conditional styling to a component. To address this, I created a component-level stylesheet called MyComponent.module.css, which includes the following styles: .primary { color: ...

Even when hovering out, jQuery maintains its hover styles

I have a jQuery script that displays a content box when hovering over a button, with the button's hover class activated. The goal is to maintain the hover styles on the button even when the mouse hovers inside the displayed content box. However, if th ...

How can users create on-click buttons to activate zoom in and zoom out features in a Plotly chart?

I am currently working on an Angular application where I need to implement zoom in and zoom out functionality for a Plotly chart. While the default hoverable mode bar provides this feature, it is not suitable for our specific use case. We require user-cr ...

Instruct Vue to scan through a directory full of images without altering the filenames of the images

I came up with a method to instruct Vue to search in a file and assign images to the corresponding number of cards. So far, it's working perfectly. However, I'm curious if there is a more efficient way to achieve this. The current drawback is th ...