Generating a tree structure using a JavaScript array

Looking to build a tree structure from a given list of data where the paths are represented like:

A-->B-->C-->D-->E..
A-->B-->C-->D-->F..
A-->F-->C-->D-->E..
.
.
.

All possible data paths are stored in an array. The desired output should look like:

                     A
                       -B
                         -C
                           -D 
                              -E
                              -F
                       -F
                         -C
                           -D
                             -E 

Is there a way to achieve this using JavaScript? I am looking for a function called createTreeFunction :)

function parseData(data)
  {


   $.each(data, function (i, p) {
                   var arr = p.split("--->");

                 createTreeFunction(p);

                  });

   };
  function parseData(data)
      {


       $.each(data, function (i, p) {
                       var arr = p.split("--->");

                     createTreeFunction(p);

                      });

   };

Answer №1

There are two main structures that can be used for building a tree with children: one using an array (Solution A) and the other using an object (Solution B).

An advantage of using an array over an object is the ability to directly iterate over the children. With an object, you first need to retrieve the keys before iteration is possible.

On the other hand, if you already know a child, accessing it through the key is faster. This also applies when inserting new nodes into the tree.

When using a children array, a getChild function is needed to check if a child is present.

Note: The provided data does not ensure the uniqueness of identifiers.

Solution A with arrays for children:

function Node(id) {
    this.id = id;
    this.children = []; // array
}

Node.prototype.getChild = function (id) {
    var node;
    this.children.some(function (n) {
        if (n.id === id) {
            node = n;
            return true;
        }
    });
    return node;
};

var path = ['A-->B-->C-->D-->E', 'A-->B-->C-->D-->F', 'A-->F-->C-->D-->E'],
    tree = new Node('root');

path.forEach(function (a) {
    var parts = a.split('-->');
    parts.reduce(function (r, b) {
        var node = r.getChild(b);
        if (!node) {
            node = new Node(b);
            r.children.push(node);
        }
        return node;
    }, tree);
});

document.getElementById('out').innerHTML = JSON.stringify(tree, 0, 4);
<pre id="out"></pre>

Solution B with objects for children:

function Node(id) {
    this.id = id;
    this.children = {}; // object
}

var path = ['A-->B-->C-->D-->E', 'A-->B-->C-->D-->F', 'A-->F-->C-->D-->E'],
    tree = new Node('root');

path.forEach(function (a) {
    var parts = a.split('-->');
    parts.reduce(function (r, b) {
        if (!r.children[b]) {
            r.children[b] = new Node(b);
        }
        return r.children[b];
    }, tree);
});

document.getElementById('out').innerHTML = JSON.stringify(tree, 0, 4);
<pre id="out"></pre>

Both solutions utilize Array#forEach and Array#reduce for iterating through the given strings and returning the reference to the actual id. In case an id is not found, a new instance of the node is created and added to the array or object. The reference is then returned for the next id check.

Answer №2

Two highly effective Object methods that I have developed for such scenarios are

Object.prototype.getNestedValue()
and
Object.prototype.setNestedValue()
. With the use of these functions, handling this task becomes as simple as a single line of JavaScript code.

Object.prototype.getNestedValue = function(...a) {
  return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
};
Object.prototype.setNestedValue = function(...a) {
  return a.length > 2 ? typeof this[a[0]] === "object" && this[a[0]] !== null ? this[a[0]].setNestedValue(...a.slice(1))
                                                                              : (this[a[0]] = typeof a[1] === "string" ? {} : new Array(a[1]),
                                                                                 this[a[0]].setNestedValue(...a.slice(1)))
                      : this[a[0]] = a[1];
};

var data = "A-->B-->C-->D-->E\nA-->B-->C-->D-->F\nA-->F-->C-->D-->E",
  datarr = data.split("\n").map(e => e.split("-->")), // get your list in an array
       o = {};
datarr.forEach(a => !o.getNestedValue(...a) && o.setNestedValue(...a,null));

console.log(JSON.stringify(o,null,2));

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

Having issues with retrieving data using findOne or findById in Express and Node JS, receiving undefined values

Currently, I am working on a microservice dedicated to sending random OTP codes via email. Below is the code for my findbyattr endpoint: router.get('/findbyattr/:email', async (request, response) =>{ try { let requestEmail = reque ...

Step-by-step guide on eliminating the modal post-validation

Newbie in reactjs looking for help with modal validation issue. Goal: Press submit button inside modal, validate, then close the modal. Want to reuse modal for another row. Problem: I'm having trouble making the function work for a new row after ...

Experiencing issues with applying bootstrap style to pagination when using react-js-pagination

I am currently utilizing the react-js-pagination library to showcase page numbers within my application. Bootstrap has been included in the public/index.html file and can be accessed using className in other components. When it comes to the Pagination com ...

the order of initialization in angularjs directives with templateUrl

In my current scenario, I am faced with a situation where I need to broadcast an event from one controller and have another directive's controller receive the message. The problem arises because the event is sent immediately upon startup of the contro ...

Using Node.js to dissect a nested JSON array into individual JSON objects

Seeking guidance on how to efficiently parse nested arrays into separate objects using Node.js. Your assistance would be greatly appreciated. I aim to exclude the following from the final output- "Status": "0", "Message": "OK", "Count": "3724", AND I w ...

The time in Europe/Moscow timezone is exactly one hour ahead of the original date

Can someone please clarify why this historical date appears to be increased by one hour when I convert it to the Moscow Timezone? I am currently using JDK version 1.6.0_12. 2011-04-02T11:39:46+0300 --> Sat Apr 02 12:39:46 MSK 2011 // 11:39 --> 1 ...

Tips for applying multiple style properties to an element using JavaScript

I have been experimenting with different versions of this code in an attempt to modify a specific element for a coding challenge, but none of them seem to successfully change multiple styling properties of the element upon clicking on a button. Would great ...

Utilize a JSON file to generate a network visualization using the vis.js library

I am currently working with vis.js to generate a visualization. In the example code, I am using the file saveAndLoad.html. The save function works well as it allows me to export a json file. However, I am encountering an issue when trying to load the jso ...

Is it possible to continuously re-render a React Functional Component with Axios and useState/useEffect?

Seeking assistance with creating a React Functional Component using Typescript to fetch data from an API and pass it to another component. However, encountering the error message "Error: Too many re-renders. React limits the number of renders to prevent an ...

Cross-Origin Resource Sharing (CORS) issue: The Access-Control-Allow-Headers in preflight response does not allow the Authorization request header field

I am currently attempting to send a request from one localhost port to another. Specifically, I am utilizing angularjs on the frontend and node on the backend. Given that this is a CORS request, in my node.js code, I have implemented the following: res.h ...

Utilizing React and Material-UI to create an autocomplete feature for words within sentences that are not the first word

Looking to enable hashtag autocomplete on my webapp, where typing #h would display a menu with options like #hello, #hope, etc. Since I'm using material-ui extensively within the app, it would be convenient to utilize the autocomplete component for th ...

React Table Pagination Bug with Material UI Library

I am currently using Material UI and referencing the table sample provided at https://material-ui.com/demos/tables/. However, when attempting to implement the Custom Table Pagination Action according to the sample, I encountered an error. The error "inher ...

Center-align the text in mui's textfield

What I'm looking for is this: https://i.stack.imgur.com/ny3cy.png Here's what I ended up with: https://i.stack.imgur.com/vh7Lw.png I attempted to apply the style to my input props, but unfortunately, it didn't work. Any suggestions? Than ...

The placeholder of a select component within a wrapper component remains the same, even though the value may change

I am experiencing an issue with a select component where the placeholder does not update when I click on its options. The select component is wrapped within another component that acts as its title and paragraph outline. This problem also occurs with anoth ...

Can you retrieve a reference/pointer to a specific property of an object in JavaScript?

I am looking to generate an HTML <input> element, and then access its value property so I can update the value through that reference: var input = document.createElement('input'); var valueRef = &(input.value); *valueRef = "Hello world!" ...

Tips for executing a callback function when triggering a "click" event in jQuery?

Having trouble triggering a custom event in the callback of a trigger call. Attempted solutions: var $input = $( ".ui-popup-container" ).find( "input" ).eq(2); function runtests () { console.log("clicked the input"); }; $input.trigger('click&ap ...

Node.js is receiving an empty body from Postman when using form-data in the request

Even though I've searched extensively, I still have not found a solution to my specific issue despite it being asked before. const express = require("express"); require("dotenv").config({ path: ".env", }); const PORT = ...

Using jest in typescript to simulate HttpRequest body and InvocationContext in @azure/functions

I have the following function and I am trying to write a test for it, but I'm having trouble figuring out how to mock HttpRequest import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; export async function ...

What steps can I take to correct my code so that it only shows a single table?

I'm facing an issue while trying to display my dynamic JSON data. It's rendering a table for each result instead of all results in the same table. My array data is coming from the backend API. const arr = [ { "Demo": [ ...

Toggle the class of a div when clicked and then change the class of another div

In my website, I have a site overlay Div (#site-overlay) that is currently set as display:none. I am looking to change the class to block when I hover and click on the menu buttons. I can use both vanilla JavaScript and jQuery to achieve this. The menu it ...