Is there a way to transform a basic array into an array containing objects?

In my Vue.js project, the API data is returned in a flat array format. I need to restructure this data into a hierarchical tree structure by assigning parent IDs to their corresponding parent items.

I attempted to achieve this but ended up with an empty tree. Here is the code snippet:

convertToTree(data) {
  const tree = [];
  const mapped = {};
  for (let i = 0; i < data.length; i += 1) {
    mapped[data[i].id] = data[i];
    mapped[data[i].id].children = [];
  }
  for (let i = 0; i < data.length; i += 1) {
    if (mapped[data[i].parentId]) {
      mapped[data[i].parentId].children.push(mapped[data[i]]);
    } else {
      tree.push(mapped[data[i]]);
    }
  }

  return tree;
},

I am seeking solutions to resolve this issue. Your insights are highly appreciated.

Here is the sample data retrieved from the API:

{
  "id": 1,
  "parentId": 0
}, {
  "id": 2,
  "parentId": 0
}, {
  "id": 3,
  "parentId": 0
}, {
  "id": 4,
  "parentId": 3
}, {
  "id": 5,
  "parentId": 3
}, {
  "id": 6,
  "parentId": 4
}, {
  "id": 7,
  "parentId": 4
}, {
  "id": 8,
  "parentId": 5
}, {
  "id": 9,
  "parentId": 5
}, {
  "id": 10,
  "parentId": 0
}

This is the desired output structure:

items: [{
    id: 1,
    parentId: 0,
    children: [{
      id: 10,
      parentId: 1,
    }],
    id: 2,
    parentId: 0,
    children: [],
    id: 3,
    parentId: 0,
    children: [{
        id: 4,
        parentId: 3,
        children: [{
            id: 6,
            parentId: 4,
            children: []
          },
          {
            id: 7,
            parentId: 4,
            children: []
          },
          {
            id: 8,
            parentId: 4,
            children: []
          }
        ]
      },
      {
        id: 5,
        parentId: 3,
        children: [{
            id: 9,
            parentId: 5,
            children: []
          },
          {
            id: 10,
            parentId: 5,
            children: []
          },
          {
            id: 11,
            parentId: 5,
            children: []
          }
        ]
      }
    ]
  }]

Answer №1

To simplify the structure of the dataArray, you can iterate through each object in the array and add child objects to their respective parentObj.children arrays. Then, extract the root nodes of trees by filtering out objects without a parent.

for (obj of dataArr) {
    if (obj.parentId) {
        let parent = dataArr.find((i) => i.id === obj.parentId);
        if (parent) {
            parent.children = [...parent.children || [], obj]
            // ↑ this creates an array if parent.children is undefined, preventing errors
        }
    }
}

After this process, the updated dataArray will resemble the following:

0: {id: 1, parentId: 0}
1: {id: 2, parentId: 0}
2: {id: 3, parentId: 0, children: Array(2)}
3: {id: 4, parentId: 3, children: Array(2)}
4: {id: 5, parentId: 3, children: Array(2)}
5: {id: 6, parentId: 4}
6: {id: 7, parentId: 4}
7: {id: 8, parentId: 5}
8: {id: 9, parentId: 5}
9: {id: 10, parentId: 0}

Next, filter the dataArray to exclude objects that do not have a parent.

let newData = dataArr.filter((obj) => !obj.parentId);

The resulting newData array will contain only the root nodes of tree structures like so:

0: {id: 1, parentId: 0}
1: {id: 2, parentId: 0}
2: {id: 3, parentId: 0, children: Array(2)}
3: {id: 10, parentId: 0}

newData[2]:

2:
children: Array(2)
    0:
    children: Array(2)
        0: {id: 6, parentId: 4}
        1: {id: 7, parentId: 4}
    id: 4
    parentId: 3
    1:
    children: Array(2)
        0: {id: 8, parentId: 5}
        1: {id: 9, parentId: 5}
    id: 5
    parentId: 3
id: 3
parentId: 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

What is the best way to delete the final line of HTML within a div element?

My primary goal is to create a dynamic form where users can add or remove HTML lines using JavaScript. I have successfully implemented the function to add new lines, but I am struggling with the removal function. Below is the code I have so far: window ...

Increase in textbox size depending on selected dropdown value

Our concept involves offering three choices: Email #1 pulled from the database Email #2 retrieved from the database Input a new email Should the user select option #3, a textbox will expand at the bottom of the dropdown menu for easy entry of a new emai ...

Is there a way to dynamically hide specific ID elements in Javascript based on the size of the browser window?

I have spent countless hours searching for a solution to this issue without any success. The problem I am facing involves making certain elements on a webpage invisible when the browser window width is less than a specified size. The issue arises due to f ...

The refresh method cannot be found in 'x'. (In the context of 'x()', 'x' represents an Object instance)

Is there a way for me to access the refresh() method within my UpdateLokalListe function? Can I integrate the function into my class? I followed the instructions in this guide: https://reactnavigation.org/docs/function-after-focusing-screen Thank you ht ...

When trying to access document.cookie, an empty string is returned despite the presence of cookies listed in developer tools, and the httpOnly flag is set

There are times when I encounter an empty string while trying to access document.cookie on the login page, despite the following conditions being met: The cookies are visible in the Chrome and Firefox developer tools, The httpOnly flag of the cookie I&ap ...

Reducing Time Series Data: Comparing Average vs Largest-Triangle-Three-Buckets Technique

Currently, I am utilizing Flot Charts to create line charts that display timeseries data. To streamline the visualization process and reduce the number of data points shown, I have implemented a downsampling technique by averaging data points within the s ...

Display PHP output for a brief moment

Here is the URL: http://www.example.com/?req=welcome. In PHP, to retrieve the parameter req, you can use the following code: echo $_GET['req']; The message will be displayed in the body but it should disappear after one second. What is the be ...

Obtain the result of the Mongoose find operation

Greetings, I am facing a challenge with accessing elements returned from a find operation in Mongoose due to the asynchronous nature and callback functions. Below is the code for reference: function retrieveBudgets(email, callback) { models.User.f ...

Guide to displaying a pop-up modal containing text and an image when clicking on a thumbnail image

Recently delving into Bootstrap 3, I created a thumbnail grid showcasing images related to various projects. My goal is to have a modal window pop up when clicking on an image. Within the modal, I want to display the selected image alongside some descrip ...

Easy task tracker in Vue.js

I’m currently delving into the world of VueJS and working on a simple to-do list application. The issue I’m facing is that I can't seem to successfully pass an array to the child component responsible for displaying the list: Parent Component < ...

Ways to capture targeted requests

Utilizing NestJS and Angular 2, I have noticed that both frameworks have a similar approach when it comes to working with Interceptors. I am currently looking for the best practice to identify specific requests in order to perform additional tasks. When d ...

Refusing to handle HTTP requests in Node and Express API for MongoDB interactions

I am currently in the process of creating a basic API for performing CRUD operations on a local mongo database. Despite having what seems like correct code, the CRUD operations result in pending requests that never seem to complete. Below are snippets of ...

Hover over a DOM element to highlight it, similar to the functionality of the inspect tool

Our website features a bookmarklet that triggers an inspect-like highlighter when a user clicks a button. We are aiming for this functionality to be compatible across different browsers. To achieve this, we must be able to detect the DOM element during mo ...

A function that retrieves the empty values from an array and returns undefined if there

After undergoing a time-consuming process, the sample below shows that the array values are returned empty. function myFunction() { let myArray = []; let pastArray = [1, 2, 6, 7, 8, 1, 9, 6, 0] pastArray.forEach(item =>{ setTimeout(function(){ myA ...

Triggering AJAX call from several buttons within a single page in Django

Hey there! I'm currently working on implementing a voting feature using Ajax in my Django-based website. The issue I'm facing is that users can only vote on the first entry, but I want them to be able to vote on all entries. Can you assist me wit ...

Tips for saving a Cytoscape.js diagram as an image

Currently, I am diving into learning Cytoscape.js. After successfully creating an HTML file with a basic graph, I attempted to export the graph to an image using the following code: var png64 = cy.png(); // Inserting the png data in an img tag document.qu ...

Replacing an array element by a specific index number in a React application

I am dealing with an array of [false,true,false,false,true] and I am looking to update the boolean values based on their index numbers. I have been trying to solve this problem in react, but haven't found a workable solution yet. this.setState({ ...

Order objects in an array based on various criteria using Javascript

In sorting an array of objects, I have two rules that need to be followed in priority: The numbers must be in numerical order The times must be in chronological order It is essential for the objects to be sorted not only by numbers but also by time. For ...

Error message: The callback function provided is not valid

While trying to improve my searching and updating functionality, I developed a method as shown below: mergeAinBbyAttr: function(a, b, attr, val, cb) { async.forEach(a, function(itemA, callbackA) { async.forEach(b, function(itemB, callbackB) { ...

Having trouble with DataTables functionality in Laravel blade views?

Blade template with a query: @extends('2a.layouts.master') <link rel="stylesheet" href="//cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css"> <script src="https://code.jquery.com/jquery-3.3.1.js"></script> <script s ...