What is the best way to transform an array of objects into a nested array through shuffling

I am dealing with a diverse array of objects, each structured in a specific way:

data = [
    {
        content: {
            ...,
            depth: 1
        },
        subContent: []
    },
    {
        content: {
            ...,
            depth: 2
        },
        subContent: []
    },
    {
        content: {
            ...,
            depth: 3
        },
        subContent: []
    },{
        content: {
            ...,
            depth: 2
        },
        subContent: []
    },
    {
        content: {
            ...,
            depth: 1
        },
        subContent: []
    },
]

The desired structure for these objects is as follows:

result = [
    {
        content: {
            ...,
            depth: 1
        },
        subContent: [
            {
                content: {
                    ...,
                    depth: 2
                },
                subContent: [
                    {
                        content: {
                            ...,
                            depth: 3
                        },
                        subContent: []
                    }
                ]
            },
            {
                content: {
                    ...,
                    depth: 2
                },
                subContent: []
            },
        ], 
        {
            content: {
                ...,
                depth: 1
            },
            subContent: []
        },
    },
]

To achieve this structure, I've created a loop that iterates through the array and arranges higher depth objects within lower ones. If they are not on the same depth level, the object will be placed at the appropriate nested level based on its depth.

for (let i = arr.length-1; i > 0; i--) {
  if (arr[i].content.depth === arr[i-1].content.depth + 1) {
    arr[i-1].subContent.push(arr[i]);
    arr.splice(i, 1);
  } else {
    let index = this.findNextLowerIndex(arr[i].content.depth, arr);

    // console.log(index);
    if (arr[index]) {
      arr[index].subContent.push(arr[i]);
      arr.splice(i, 1);
    }
  }
}




findNextLowerIndex(depth: number, arr: any[]): number {
    let findIndex = depth - 1;

    for (let i = arr.length-1; i > 0; i--) {
        if (arr[i].content.depth === findIndex) {
            return i;
        }
    }
}

This approach works well for most scenarios, however, it struggles when dealing with multiple layers of subContent. For instance, when the array depths are arranged like 4, 3, 4, 3, 2, 1, the nesting might not be optimal. It can lead to missing relationships between certain layers of subContent.

If you have any suggestions or ideas on how to improve this nesting logic, feel free to share!

Answer №1

Do you need assistance with something similar to this?

const info = [{ content: { level: 1 }, subContent: [] }, { content: { level: 2 }, subContent: [] }, { content: { level: 3 }, subContent: [] }, { content: { level: 2 }, subContent: [] }, { content: { level: 1 }, subContent: [] }]
let output = [];
for (item of info) {
    let parentNode = info.find(value => value.content.level == item.content.level - 1)?.subContent || output
    parentNode.push(item)
}
console.log(output)

Answer №2

This might just be the perfect solution you've been searching for.

const info = [
  { data: { level: 1 }, subData: [] },
  { data: { level: 2 }, subData: [] },
  { data: { level: 3 }, subData: [] }, 
  { data: { level: 2 }, subData: [] },
  { data: { level: 1 }, subData: [] },
];

const result = info.reduce((accumulator, current) => {
  if (current.data.level === 1) {
    accumulator.push(current);
  } else {
    let node = accumulator[accumulator.length - 1]; // Getting the last node
    while (node.data.level !== current.data.level - 1) {
      if (node.subData) {
        node = node.subData[node.subData.length - 1];
      } 
    }
    node.subData.push(current);
  }
  return accumulator;
}, []);

console.log(result);

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

Unveiling the essence of Lodash's differenceBy functionality

I am facing a challenge with two arrays of objects. I need to identify the differences between the newData and oldData arrays based on their identifiers. Specifically, I want to display objects from oldData whose identifiers are not present in newData. Her ...

Verify the entered information in the input field and showcase it in the display box after pressing the ENTER key

I need to display selected values of a tree structure in a show box on the other side of the page using code. However, I also need to include HTML input boxes in some lines of the tree structure so that users can input data. The challenge is getting the in ...

Exploring the capabilities of Angular 2 and delving into inquiries regarding IIS

I'm diving into the world of Angular 2 as a beginner. Previously, I used to include JavaScript (like jQuery.js) in my HTML and then upload the finished page to my IIS website. Now that I'm learning Angular 2, I've had to install Node.js, NP ...

What is the best way to display the selected value of a radio button in React Native?

Being relatively new to React Native and mobile app development in general, I am facing an issue while trying to display the values assigned to different radio buttons within a radio button group. My code snippet is provided below: RadioButtons.js im ...

Express.js is still displaying the 'Not Found' message even after deleting the initial code

Despite multiple attempts to resolve what I initially thought was a caching issue by completely removing all code from my server, I am still facing the same problem: The default error handling provided by Express Generator in the app.js file contains the ...

Error in AngularJS v1.2.5 when using textarea with placeholder attribute in IE11

Having trouble with an Angular JS v1.2.5 form that is not functioning in IE11, despite working perfectly in Firefox, Chrome, and Safari. The issue seems to be related to using interpolation inside the placeholder attribute of a textarea. <body ng-con ...

Converting JSON-style data into a string with the power of node mysql

Just a quick note - I'm a total newbie in the world of web development, so I might be missing an obvious solution here. My challenge is to insert a dataset into a MySQL database using nodejs/expressjs/mysql. I've managed to establish a connecti ...

What is the process for adjusting the input value dynamically in reactjs?

I am working on a dynamic time input row and I need to ensure that the values are updated correctly. This is the code snippet I am using: https://codesandbox.io/s/624vq8y7y3 When I run the code, the values in the TimeInput field do not change as expected ...

Adding comments in TypeScript: A quick guide

Hey there, I'm new to TS and could use some help. Here is the code snippet I have: I want to comment out the logo but adding "//" and '/*' doesn't seem to work. This is what I tried: // <LogoComponent classes={{container: style.log ...

Converting Data Types in Typescript

So I'm working with Data retrieved from a C# Rest Server. One of the values in the array is of type Date. When I try to perform calculations on it, like this: let difference = date1.getTime() - date2.getTime(); I encounter the following error messag ...

Issues with Toggling Visibility in HTML, CSS, and Javascript

Currently, I am working on a website and following a tutorial called "Creating Slideshow using HTML, CSS, and Javascript" by W3Schools. In the project, I want to hide the thumbnail images located at the bottom and the navigation arrows initially and have t ...

Encountered an npm installation error: The rollbackFailedOptional issue arose during the npm session with the verb npm-session a0d68 while attempting the command npm install --save

Every time I attempt to install babel, I encounter the following error message: rollbackFailedOptional: verb npm-session a0d68 The version of Node currently installed is 12.16.1 The version of npm being used is 6.13.4 All I want is to get babel up and ...

tips for concealing the shadow of a draggable div during the dragging process

I am facing an issue with a draggable div. When I drag the div, the shadow also moves along with it. I want to find a way to hide this shadow while dragging. <div draggable="true" (dragstart)="mousedown($event)" (drag)="dra ...

"Exploring the process of assigning input data to a different variable within a Vue component

Reviewing the code snippet I currently have: <template> <div> <input v-model.number="money"> <p>{{ money }}</p> </div> </template> <script> name: 'MyComponent', data () { ...

What is the best way to swap out constants with a method or variable?

One of the functions I've created calculates forced vital capacity by identifying the last positive number before a negative number in a dataset sequence: def FVC(self, data): count = 0 for i in range(len(data)): # chec ...

Connecting an HTML box to a JavaScript function for the desired outcome: How to do it?

My goal is to connect the input box with id="b" (located inside the div with id="but1") with a JavaScript function that calculates values within an array. Although my junior logic review didn't detect any issues in the code, what mistakes could I have ...

Attempting to implement ajax for form submission, however finding that the $_POST array is coming back as empty

I'm attempting to send JavaScript arrays to a new page using Ajax. Although there are numerous questions on this topic on Stack Overflow, I have decided to implement Ajax in the following manner after examining various answers: var test = {}; test[& ...

Dividing an AngularJS module across multiple iFrames on a single webpage

Currently, I am working on a web application that consists of 1 module, 5 pages, and 5 controllers. Each HTML page declares the same ng-app. These pages are loaded within widgets on a web portal, meaning each page is loaded within an iFrame in the portal. ...

What is the best way to incorporate a state variable into a GraphQL query using Apollo?

My current challenge involves using a state as a variable for my query in order to fetch data from graphQl. However, I'm encountering an issue where the component does not read the state correctly. Any suggestions on how to solve this? class usersSc ...

Guide to shutting down a print dialogue in a web browser with javascript

Looking for a way to close the print window of a browser using JavaScript or any other method, with JavaScript being the preferred option. Any help on closing the print window for IE, Chrome and Safari would be greatly appreciated. Please assist.. Thank ...