Change an array of objects with parent child connections into a nested object structure

Imagine having a collection of objects with parent-child relationships like the one shown below:

[
  { A1: [ "B1" ] },
  { B1: [ "C11", "C12", "C13" ] },
  { C11: [ "D100", "D111", "D112", "D113", "D131" ] },
  { D100: [ "E1000", "E1100" ] }
]

How would you go about transforming the above array into a hierarchical object that accurately represents these relationships? The resulting object should look like this:

{
A1: 
{
    B1:
    {
        C11: 
        {
            D100: ["E1000", "E1100"],
            D111: [],
            D112: [],
            D113: [],
            D131: []
        },
        C12: [],
        C13: []
    }
}

}

I have attempted various recursive methods utilizing reduce, but I am still struggling to successfully convert all levels.

Answer №1

If you want to achieve the desired outcome through recursion, the following example may be a little clunky but gets the job done:

const array = [
  { A1: [ "B1" ] },
  { B1: [ "C11", "C12", "C13" ] },
  { C11: [ "D100", "D111", "D112", "D113", "D131" ] },
  { D100: [ "E1000", "E1100" ] }
]

// Creating an object structure

const result = array.reduce((prev, current) => {
  Object.entries(current).map(([key, value]) => {
    if (value) {
      prev[key] = {};
      value.map(el => prev[key][el] = {});
    }
  });
  return prev;
}, {})

// Loop to show relationships

Object.values(result).map(value => {
  if (Object.keys(value).length) {
    represent(value, result);
  }
})

function represent(value, obj) {
  Object.keys(value).map(key => {
    if (obj[key]) {
      value[key] = { ...obj[key] };
      delete(obj[key]);
      represent(value[key], obj);
    }
  })
}

// Converting and linking empty objects to arrays

associate(result);

function associate(obj) {
  Object.entries(obj).map(([key, value]) => {
    const values = Object.values(value).filter(o => Object.keys(o).length);
    if(values.length){
      associate(value)
    }else{
      if(Object.keys(value).length === 1) {
        obj[key] = [];
      }else {
        obj[key] = Object.keys(value);
      }
    }
  });
}

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

Answer №2

Suppose you have an object with a similar pattern, you can extract objects with references to other nested objects.

If you want to receive different values, such as arrays instead of objects, you can indicate this in the input data.

const
    data = [{ A1: ["B1"] }, { B1: ["C11", "C12", "C13"] }, { C11: ["D100", "D111", "D112", "D113", "D131"] }, { D100: ["E1000", "E1100"] }],
    result = data.reduce((r, o) => {
        Object
            .entries(o)
            .forEach(([k, a]) => a.forEach(l => (r[k] || r._)[l] ??= r[l] = {}));
        return r;
    }, { _: {} });

console.log(result._);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

The Tooltip fails to display my content when hovered over for the first time, but it appears on the second attempt

Here is the code snippet: <a href="", class="cancel-invitation-from-other" title="Close" onmouseover = "show_bookclub_book_tooltip('Decline invitation','cancel-invitation-from-other');" data-placement="top"></a> and this i ...

Navigate the child div while scrolling within the parent div

Is there a way to make the child div scroll until the end before allowing the page to continue scrolling when the user scrolls on the parent div? I attempted to use reverse logic Scrolling in child div ( fixed ) should scroll parent div Unfortunately, it ...

Unraveling the Mystery of jQuery Syntax

Upon reviewing jquery.ui-1.8.11.js: $.extend(Datepicker.prototype, { /* A unique class name appended to elements indicating they are configured with a date picker. */ markerClassName: 'hasDatepicker', /* For debugging purposes (if e ...

Prevent certain dates from being selected in a designated input field

I am facing an issue with disabling certain array dates for a specific input field in a datepicker calendar. Even though I have included the script to exclude those dates, they are not getting disabled for that particular input field. html <input cla ...

Using Three.js to Spin Cylinder Towards a Vector3 Destination

I've attempted a thorough search, but unfortunately, I haven't come across any solutions that address my issue: I have a vector and a CylinderGeometry Mesh. My goal is to make the cylinder face the direction indicated by the vector. The input pa ...

By employing timeUpdate in conjunction with currentTime

I am looking to utilize the timeUpdate and currentTime functionalities to display or hide a div at a specific time during video playback. I have been able to make it work, but it seems to be showing and hiding every second I specify. Below is the code I ...

Creating an array of data from JSON using JavaScript and displaying it in a chart using ApexChart

I am attempting to generate a chart displaying the value of Bitcoin in Euro. The data is fetched from JSON and converted into an array for the ApexChart series data (ApexData['xbtToEuro']) along with a list of dates. Despite my console indicatin ...

Make sure to deactivate the submit button when the <textarea> field is empty, but remember to re-enable it once text is added

I'm facing an issue with disabling and enabling the submit button based on the contents of a textarea. I initially set the submit button to a disabled state and attempted to use JavaScript code to enable it when text is typed in the textarea. However, ...

When using Express, some static files may display raw code instead of rendering the intended HTML content

I am facing an issue with an anchor link in my layout.hbs file. The link is supposed to direct to layout2.hbs, but instead of rendering proper HTML, it displays a page of raw code. Upon checking my console messages, I can see the following: GET / 304 28. ...

Event for updating a cursor in Mongo/Meteor

I am working on developing a chat application using Angular/Meteor technology. Query Is there a method to identify when changes occur in the MongoDB Cursor? Is there an event that gets triggered when a new row is added? When I send a message to another ...

Troubleshooting a malfunctioning custom filter in AngularJS

I'm having trouble implementing a custom filter in AngularJS. The output is not what I expected. Here is the code I have: script.js var myApp = angular.module('myModule', []); myApp.filter("gender", function(){ return function(gender){ ...

I'm so confused about the operation of each method in this context

I am experimenting with a simple process involving setTimeout function. My goal is to make the letters of a name appear individually and gradually at different times. For example, if the name is NAZ, I want the letters to appear in this order: first N, the ...

Changing the image source using Javascript and extracting part of the URL

i'm attempting to extract the image url from a series of urls in a loop, removing the hash portion () without the hash (?sqp=-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE=&rs=AOn4CLDi79vN15idfFETvntyC9yat7FvZQ). I've managed to mak ...

Tips for passing a URL variable into an Ajax script to prefill a form input in a search field

I have a website with a search feature that dynamically queries a database as you type in the search field, similar to Google's search suggestions. This functionality is achieved through AJAX. As the results appear on the page while you enter your se ...

Customize your select element's background using jQuery when the content changes

Here is a select element with different options to choose from: <select class="state"> <option value="1">Done</option> <option value="2">Closed</option> <option value="2">Open</option> <option v ...

React Hook Form is experiencing an excessive amount of re-renders which can lead to an infinite loop. React sets a limit on the number

Currently, I am working on displaying a field named party. Once this field is selected, a list of products should be rendered. In my project, I am using React Hook Form along with the watch hook to keep track of changes. <FormProvider {...methods}> ...

Explore the routing capabilities of the HERE Maps JS API, including features for ABR and height

Recently, I've encountered an issue with the HERE maps JS API routing feature. Specifically, I'm attempting to add restrictions based on factors like height or weight. Despite my efforts, it seems to be disregarding these restrictions. Additional ...

Having issues with FileReader and $scope.$watch in AngularJS?

Seeking assistance with a new challenge - working with files in JavaScript is uncharted territory for me. I have a directive with a template that includes an input file and upload button. <input type="file" ng-file-select ng-model="files"> <butto ...

Navigating to a particular div using a click event

I am trying to achieve a scrolling effect on my webpage by clicking a button that will target a specific div with the class "second". Currently, I have implemented this functionality using jQuery but I am curious about how to accomplish the same task using ...

Retrieving specific data from nested arrays in Vue.js

I am currently working on Vue.js template development and facing an issue with filtering nested data in a faq section. When I try to add a search bar, the nested data array returns all data without proper filtering. Dom <v-container> <v ...