What is the best way to interweave my objects within this tree using recursion?

I am working on creating a new function called customAdd() that will build a nested tree structure like the one shown below:

 let obj = []

let obj1 = {
    key: "detail1Tests",
    id: "94d3d1a2c3d8c4e1d77011a7162a23576e7d8a30d6beeabfadcee5df0876bb0e"
}

let obj2 = {key: "detail1Tests.detail2Tests", id: "5b091b37a9efc9d0567a4beac0bb20fcdf9796f4b71e239da6ac0c53e3488838"}

let obj3 = {key: "detail1Tests.detail2Tests.detail3Tests", id: "0b60c29d6e309be95ef33b0ad137623c5712a9a47613ce5e561871001c71bd3b"}

let result = this.customAdd(obj, obj1);
console.log(result);

let result1 = this.customAdd(result, obj2);
console.log(result1);

let result2 = this.customAdd(result1, obj3);
console.log(result2);
};

The expected output for 'result' should be:

 children: {
    detail1Tests: [{
            id: " 94d3d1a2c3d8c4e1d77011a7162a23576e7d8a30d6beeabfadcee5df0876bb0e "
        }]

'result1' should look like this:

 children: {
    detail1Tests: [{
            id: " 94d3d1a2c3d8c4e1d77011a7162a23576e7d8a30d6beeabfadcee5df0876bb0e "
            children: {
                detail1Tests.detail2Tests: [{
                        id: "5b091b37a9efc9d0567a4beac0bb20fcdf9796f4b71e239da6ac0c53e3488838"
                    }
                ]
            }
        }]

Finally, 'result2' should resemble:

 children: {
    detail1Tests: [{
            id: " 94d3d1a2c3d8c4e1d77011a7162a23576e7d8a30d6beeabfadcee5df0876bb0e "
            children: {
                detail1Tests.detail2Tests: [{
                        id: "5b091b37a9efc9d0567a4beac0bb20fcdf9796f4b71e239da6ac0c53e3488838"
                        children: {
                            detail1Tests.detail2Tests.detail3Tests: [{
                                    id: "0b60c29d6e309be95ef33b0ad137623c5712a9a47613ce5e561871001c71bd3b"
                                }
                            ]
                        }
                    }
                ]
            }
        }]

As you can see, the function I've built only works on the first level of nesting. If you have any suggestions on how to extend it to deeper levels, please let me know.

 customAdd(obj, subObj){
    let obj2 = {children: {[subObj.key]: [{id: subObj.id}] }}
    if(obj.children){
        let obj3 = obj.children;
        var kyz = Object.keys(obj3);
        let obj4 = obj3[kyz[0]]
        this.customAdd(obj4, subObj)
    }
    else {
        return {...obj,...obj2};
    }
}

Any insights on how to achieve deeper nesting are welcome.

Answer №2

There were some issues with the customAdd() function and it required certain modifications to achieve its intended goal. Here is the updated version:

customAdd(obj , subObj){
    
    if(obj.children){
      let obj3 = obj.children;
     var kyz = Object.keys(obj3);
     let obj4 = obj3[kyz[0]]
    return  this.customAdd(obj4[0] , subObj)
    }
    else {
      obj.children=obj2.children;
      return ;
    }
   
  }

It's important to note that the object passed to this function will be altered. To preserve the original object and store results independently, a deep copy of the object can be created using the following syntax:

let result = JSON.parse(JSON.stringify(obj));

With this in mind, the code would look like this:

this.customAdd(obj, obj1);
  var result = JSON.parse(JSON.stringify(obj));
  console.log(result);  

  this.customAdd(obj, obj2);
  var result1 = JSON.parse(JSON.stringify(obj));;
  console.log(result1);

  this.customAdd(obj,obj3);
  var result2 = JSON.parse(JSON.stringify(obj));;
  console.log(result2);

Answer №3

As per the suggestion of designreact, an alternative approach could be implemented using Ramda's assocPath function (or a similar one from lodash).

const customAdd = ({key, ...rest}, o) =>
  assocPath (key .split ('.') .flatMap (k => ['children', k, 0]), rest, o)


let obj1 =  {
  key: "detail1Tests",
  id : "94d3d1a2c3d8c4e1d77011a7162a23576e7d8a30d6beeabfadcee5df0876bb0e"
}

let obj2 = {
  key: "detail1Tests.detail2Tests",
  id: "5b091b37a9efc9d0567a4beac0bb20fcdf9796f4b71e239da6ac0c53e3488838"}

let obj3 = {
  key: "detail1Tests.detail2Tests.detail3Tests",
  id: "0b60c29d6e309be95ef33b0ad137623c5712a9a47613ce5e561871001c71bd3b"
}


const results1 = customAdd (obj1, {})
const results2 = customAdd (obj2, results1)
const results3 = customAdd (obj3, results2)

console .log (results1)
console .log (results2)
console .log (results3)
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js"></script>
<script> const {assocPath} = R </script>

The process involves dividing the key into segments, where each segment is prefixed with "children" and suffixed with 0. For example,

"detail1Tests.detail2Tests"
transforms into
["children", "detail1Tests", 0, "children", "detail2Tests", 0]
, which matches the structure required by Ramda's assocPath method.

However, incorporating Ramda solely for this purpose may be unnecessary. A custom version of assocPath can be created easily by leveraging another function inspired by Ramda called assoc. The two functions combined would look like this:

const assoc = (p, v, o) => 
  Number .isInteger (p) && Array .isArray (o)
    ? [... o .slice (0, p), v, ... o .slice (p + 1)]
    : {... o, [p]: v}

const assocPath  = ([p, ... ps], v, o) => 
  p == undefined
    ? o
    : ps.length == 0
      ? assoc (p, v, o)
      : assoc (p, assocPath (ps, v, o [p] || (o [p] = Number.isInteger (ps [0]) ? [] : {})), o)

I recommend reconsidering the output structure unless it is necessary to align with an external system. The current format might not be efficient or intuitive for your use case. An improved structure could resemble:

{
    detail1Tests: {
        id: "94d3d1a2c3d8c4e1d77011a7162a23576e7d8a30d6beeabfadcee5df0876bb0e",
        detail2Tests: {
            id: "5b091b37a9efc9d0567a4beac0bb20fcdf9796f4b71e239da6ac0c53e3488838",
            detail3Tests: {
                id: "0b60c29d6e309be95ef33b0ad137623c5712a9a47613ce5e561871001c71bd3b"
            }
        }
    }
}

This structure can be easily achieved with the following code:

const customAdd = ({key, ...rest}, o) =>
  assocPath (key .split ('.'), rest, o)

If you prefer retaining the "children" node in each segment, you can consider a format like:

{
    children: {
        detail1Tests: {
            id: "94d3d1a2c3d8c4e1d77011a7162a23576e7d8a30d6beeabfadcee5df0876bb0e"
            children: {
                detail2Tests: {
                    id: "5b091b37a9efc9d0567a4beac0bb20fcdf9796f4b71e239da6ac0c53e3488838",
                    children: {
                        detail3Tests: {
                            id: "0b60c29d6e309be95ef33b0ad137623c5712a9a47613ce5e561871001c71bd3b"
                        }
                    }
                }
            }
        }
    }
}

Incorporate the following code to achieve this desired structure:

const customAdd = ({key, ...rest}, o) =>
  assocPath (key .split ('.') .flatMap (k => ['children', k]), rest, o)

The additional array layer in this nested format may not provide significant benefits and can be omitted if deemed unnecessary.

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

React Big Calendar encountered an error: The element type provided is not valid, as it is expected to be a string for built-in

Error One: The element type is invalid: it was expecting a string (for built-in components) or a class/function (for composite components), but received undefined. This could be due to not exporting your component correctly from the file where it's d ...

JWT authentication for restricted routes

I'm currently developing an application that requires users to log in and allows them to join private groups. I have successfully implemented the login part using JWT, but I'm struggling with how to prevent users from joining private groups until ...

How to drop several pins on Google Maps with JavaScript

I am working on incorporating multiple markers into a Google map using ajax, javascript, and php. Although there are no errors in my code, the markers are not appearing as expected. I would greatly appreciate any assistance with this issue. Please refer to ...

Implementing chance.js in an Angular 4.x Component's ngOnInit() Method

I just started using angular 4.x and I'm trying to load change.js in the ngOnInit() function. I've attempted a few things but nothing seems to be working. Here is the code snippet: This is the code I have so far: import { Component, OnInit, In ...

Is there a way to manipulate my csv values so that they all appear in a single column?

I've been using the ngx-papaparse library to convert an array into a CSV file. However, after downloading the CSV file and opening it with Excel, I noticed that my values are not appearing in the correct columns. This is the function I am using: dow ...

Switch up the CSS file based on the URL route

My project consists of the following files: App.vue, changcolor.vue, config.json, main.js, index.html, xyz.css, abc.css. I need a solution where based on the URL, the appropriate CSS file is applied. For instance, if the URL is "xyz.local.com" then xyz.cs ...

Attaching an event listener to elements with a specified Class name

Currently facing a challenge where I am trying to implement a function that captures click events on squares. The objective is to capture the click event on every button with the square class. import { Component, OnInit } from '@angular/core&apos ...

Utilize socket communication with node.js to monitor and identify user

I'm attempting to find a method to unsubscribe from a Redis channel when the user navigates to another page within our website. I have attempted to detect a disconnect socket event when the user clicks on a link, but unfortunately, the event is never ...

'ng build' operation halted - Angular

Having issues running ng build in order to generate my /dist folder for hosting on a remote server. While npm install went smoothly, the ng build command keeps aborting. Here is the error message: ng build[3725390]: ../src/node_worker.cc:525:static void ...

The Ionic and Angular application solely displays dynamic HTML with no encapsulation using ViewEncapsulation.None

I'm struggling to grasp the concept of encapsulation: ViewEncapsulation.None within the @Component. @Component({ selector: 'app-home', templateUrl: 'home.page.html', styleUrls: ['home.page.scss'], encapsulation: ...

What methods are most effective when utilizing imports to bring in components?

Efficiency in Component Imports --Today, let's delve into the topic of efficiency when importing components. Let's compare 2 methods of importing components: Method 1: import { Accordion, Button, Modal } from 'react-bootstrap'; Meth ...

I'm sorry, but we were unable to locate the /bin/sh

After running a command using execSync that runs with sh, I observed the following: spawnSync /bin/sh ENOENT bin is now included in the PATH environment variable. Any ideas on this issue? ...

Using the spread operator in a component's render function could potentially lead to an endless update loop

Although this issue has been addressed before in a discussion about the "You may have an infinite update loop in a component render function" warning in Vue component, the solution provided did not resolve my problem. I am seeking assistance to ...

Is it possible to utilize Angular validation directives programmatically within a personalized directive?

In my exploration of HTML inputs, I have noticed a recurring pattern specifically for phone numbers: <input type="text" ng-model="CellPhoneNumber" required ng-pattern="/^[0-9]+$/" ng-minlength="10" /> I am interested in developing a unique directiv ...

What is the proper way to specify the type for a proxy that encapsulates a third-party class?

I have developed a unique approach to enhancing Firestore's Query class by implementing a Proxy wrapper. The role of my proxy is twofold: If a function is called on the proxy, which exists in the Query class, the proxy will direct that function call ...

What is the process for calculating and determining the exact area the div should be released?

I am currently developing a drag-and-drop application using only Javascript. I have successfully implemented the dragging functionality, allowing elements to be moved randomly within the page. However, I now face the challenge of creating a drop zone with ...

Encountering a JavaScript problem in Google Chrome?

Something strange is happening when I try to place an image in the canvas... "Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(HTMLImageElement or HTMLVideo ...

ES6 Conditional Import and Export: Leveraging the Power of Conditional

Looking to implement a nested if else statement for importing and exporting in ES6? In this scenario, we have 2 files - production.js and development.js which contain keys for development and production code respectively. Additionally, there is another fil ...

Discovering an Element in jQuery through its ID using Spaces and Variables

My issue involves locating an element within another element using an ID and then adding a class when the ID is hardcoded. For example: var tableId = el.id; $('#' + tableId).find("[id='Checkout On']").addClass('highlight'); ...

Utilizing the reduce method to transform an array containing nested arrays into a different structure

I'm having trouble figuring out how to restructure the array below. I attempted to utilize the reduce function in JavaScript but unfortunately, I couldn't make it work. So far, this is the function I have come up with: var comb = [] var setEle ...