Transfer all the child nodes to the parent using the spread operator or Object.assign while preventing duplicate properties from being overwritten

I'm trying to transfer all the nodes of a child node to the parent using the spread operator or Object.assign (without relying on Lodash) while avoiding overwriting existing properties.

My initial thought was to simply append the childArray to the root object, but all my attempts have been unsuccessful.

const tree = {
  rootonlyinfo: "test",
  morefields: "another",
  comments: [{
      text: "This is comm 1",
      id: "1"
    },
    {
      text: "This is comm 2",
      id: "2"
    }
  ],
  attachments: [{
      text: "This is att 1",
      id: "1"
    },
    {
      text: "This is att 2",
      id: "2"
    }
  ],
  children: [{
    comments: [{
      text: "This is comm 3",
      id: "3"
    }],
    attachments: [{
        text: "This att 3",
        id: "3"
      },
      {
        text: "This att 4",
        id: "4"
      }
    ],
    children: [{
      comments: [{
        text: "This is comm 4",
        id: "4"
      }],
      attachments: [{
        text: "This is att 5",
        id: "5"
      }]
    }]
  }],
  childArray: {
    comments: [{
        text: "This is comm from child 1",
        id: "1"
      },
      {
        text: "This is comm from child 2",
        id: "2"
      }
    ],
    attachments: [{
        text: "This is att from child 1",
        id: "1"
      },
      {
        text: "This is att from child 2",
        id: "2"
      }
    ],
    children: [{
      comments: [{
        text: "This is comm from child 3",
        id: "3"
      }],
      attachments: [{
          text: "This att from child 3",
          id: "3"
        },
        {
          text: "This att from child 4",
          id: "4"
        }
      ],
      children: [{
        comments: [{
          text: "This is comm from child 4",
          id: "4"
        }],
        attachments: [{
          text: "This is att from child 5",
          id: "5"
        }]
      }]
    }]
  }
};

const mergedTree = [{ ...tree.childArray,
  ...tree
}];
console.log("mergedTree", mergedTree);

View code sample here: https://stackblitz.com/edit/angular-ivy-sxf2y4?file=src%2Fapp%2Fapp.component.ts

Any suggestions?

Expected Outcome:

{
   "rootonlyinfo":"test",
   "morefields":"another",
   "comments":[
      {
         "text":"This is comm 1",
         "id":"1"
      },
      {
         "text":"This is comm 2",
         "id":"2"
      },
      {
         "text":"This is comm from child 1",
         "id":"1"
      },
      {
         "text":"This is comm from child 2",
         "id":"2"
      }
   ],
   "attachments":[
      {
         "text":"This is att 1",
         "id":"1"
      },
      {
         "text":"This is att 2",
         "id":"2"
      },
      {
         "text":"This is att from child 1",
         "id":"1"
      },
      {
         "text":"This is att from child 2",
         "id":"2"
      }
   ],
   "children":[
      {
         "comments":[
            {
               "text":"This is comm 3",
               "id":"3"
            },
            {
               "text":"This is comm from child 3",
               "id":"3"
            }
         ],
         "attachments":[
            {
               "text":"This att 3",
               "id":"3"
            },
            {
               "text":"This att 4",
               "id":"4"
            },
            {
               "text":"This att from child 3",
               "id":"3"
            },
            {
               "text":"This att from child 4",
               "id":"4"
            }
         ],
         "children":[
            {
               "comments":[
                  {
                     "text":"This is comm 4",
                     "id":"4"
                  }
               ],
               "attachments":[
                  {
                     "text":"This is att 5",
                     "id":"5"
                  },
                  {
                     "text":"This is comm from child 4",
                     "id":"4"
                  },
                  {
                     "text":"This is att from child 5",
                     "id":"5"
                  }
               ]
            }
         ]
      }
   ],
   "childArray":{
      "comments":[
         {
            "text":"This is comm from child 1",
            "id":"1"
         },
         {
            "text":"This is comm from child 2",
            "id":"2"
         }
      ],
      "attachments":[
         {
            "text":"This is att from child 1",
            "id":"1"
         },
         {
            "text":"This is att from child 2",
            "id":"2"
         }
      ],
      "children":[
         {
            "comments":[
               {
                  "text":"This is comm from child 3",
                  "id":"3"
               }
            ],
            "attachments":[
               {
                  "text":"This att from child 3",
                  "id":"3"
               },
               {
                  "text":"This att from child 4",
                  "id":"4"
               }
            ],
            "children"[
                {
                  "comments":[
                    {
                      "text":"This is comm from child 4",
                      "id":"4"
                    }
                 ],
                 "attachments":[
                   {
                     "text":"This is att from child 5",
                     "id":"5"
                  }
                ]
             }
           ]
         }
       ]
     }
}

Answer №1

This method is designed for traversing one level deep, and can be extended by analyzing each individual node

const tree = {
  rootonlyinfo: "test",
  morefields: "another",
  comments: [
    {
      text: "This is comm 1",
      id: "1",
    },
    {
      text: "This is comm 2",
      id: "2",
    },
  ],
  attachments: [
    {
      text: "This is att 1",
      id: "1",
    },
    {
      text: "This is att 2",
      id: "2",
    },
  ],
  children: [
    {
      comments: [
        {
          text: "This is comm 3",
          id: "3",
        },
      ],
      attachments: [
        {
          text: "This att 3",
          id: "3",
        },
        {
          text: "This att 4",
          id: "4",
        },
      ],
      children: [
        {
          comments: [
            {
              text: "This is comm 4",
              id: "4",
            },
          ],
          attachments: [
            {
              text: "This is att 5",
              id: "5",
            },
          ],
        },
      ],
    },
  ],
  childArray: {
    testing: "i am not in parent",
    comments: [
      {
        text: "This is comm from child 1",
        id: "1",
      },
      {
        text: "This is comm from child 2",
        id: "2",
      },
    ],
    attachments: [
      {
        text: "This is att from child 1",
        id: "1",
      },
      {
        text: "This is att from child 2",
        id: "2",
      },
    ],
    children: [
      {
        comments: [
          {
            text: "This is comm from child 3",
            id: "3",
          },
        ],
        attachments: [
          {
            text: "This att from child 3",
            id: "3",
          },
          {
            text: "This att from child 4",
            id: "4",
          },
        ],
        children: [
          {
            comments: [
              {
                text: "This is comm from child 4",
                id: "4",
              },
            ],
            attachments: [
              {
                text: "This is att from child 5",
                id: "5",
              },
            ],
          },
        ],
      },
    ],
  },
};

let childArray = tree.childArray;
let combinedTree = Object.keys(tree)
  .filter((k) => k !== "childArray")
  .reduce((result, currentKey) => {
   if(Array.isArray(tree[currentKey])){
    result[currentKey] = [
      ...tree[currentKey],
      ...(childArray[currentKey] || []),
    ];
   }
    return result;
  }, {});
  combinedTree = {...tree, ...childArray, ...combinedTree}
console.log(combinedTree);

console.log("=== The console will display some references due to length, please stringify the original output for comparison ===");

console.log(JSON.stringify(combinedTree));

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

Interactive canvas artwork featuring particles

Just came across this interesting demo at . Any ideas on how to draw PNG images on a canvas along with other objects? I know it's not a pressing issue, but I'm curious to learn more. ...

Navigating back to the app after saving contacts can be achieved using React Native and the react-native-contacts library

I am currently utilizing the react-native-contacts library in my React Native application to save a contact. Prior to saving the contact, I request WRITE permission from Android. The process is successful; I open the contact form within my app and proce ...

I have experimented with both POST and GET methods in Node.js, exploring a variety

After creating a login page with a GET form, the server code includes: app.use(express.static(path.join(__dirname, 'public'))); I am facing an issue trying to implement a POST request. When I use "POST", it gives me a "CANNOT / PO ...

Implement a jQuery feature to gradually increase opacity as the user scrolls and the page loads

On a dynamically loaded page via pjax (except in IE), there are several links at the bottom. Whenever one of these hyperlinks is clicked, the page scrolls to the top while still loading. Although I am okay with this behavior, I'm curious if it' ...

Tips for resolving the error message "Uncaught TypeError: Cannot read property '0' of undefined" in React rendering

When I try to map through my list in the render function, it doesn't work, even though it works fine within my component class DesktopList extends Component { constructor(props) { super(props); this.state = { i ...

Utilizing Visual Studio: Implementing jsmin in post-build actions

After attempting to add jsmin.exe as a post-build event in my VS 2010 project, I encountered an "error code 9009" when building the project. I tested this in the command prompt and found that it works if I navigate to the folder and run: jsmin < debug ...

Unable to adjust layout when code is functioning alongside background-color

I'm looking to dynamically change the position of an item on my webpage when it is clicked. Is there a way I can achieve this without relying on id names? I currently have a code snippet that successfully changes the background color, but for some rea ...

The custom tab component in React is currently not accepting the "disabledTabs" prop

I have designed a tab component as shown below: tab/index.jsx import React from 'react'; import TabHeader from './header'; import TabBody from './body'; import TabHeaderList from './header/list'; import TabBodyList ...

Tips for tidying up duplicated typescript content sourced from a pre-existing library

Seeking guidance on implementing best practices and gaining a better understanding of my approach. After discovering the library react-google-calendar-api, I successfully installed it using npm in my React project. However, I wanted to expand its function ...

Confirm the data in each field of a form individually

I am facing an issue with a form that contains 7 fields. When I submit the form to the "register.php" page, it processes each field one by one and outputs the result as a whole. However, I need to validate the data using ajax, collect the output one by one ...

Is there a way to transform a fixed parameter into a user input value and display the function's outcome on a different page?

I am in the process of developing a straightforward web application for book searching based on ISBN. The website will feature a text input field for entering an ISBN and a submit button. Essentially, a user can enter an ISBN in the designated box, click s ...

Adding several entries into mysql with the assistance of php

I've been attempting to input multiple records into my database table, but every time I try, all I see are zeros(0) inserted into the fields. Here's what I attempted: I used a foreach loop for insertion, but unfortunately it doesn't seem to ...

Implementing a function to save a file to a nested directory in node.js

Currently, I'm utilizing node and express with the following directory structure: public img css js server.js Within server.js, I have the code snippet below for writing to a png file: fs.writeFile('testfile.png', imageData, func ...

Is the mounted hook not being triggered in a Nuxt component when deploying in production (full static mode)?

I have a component that is embedded within a page in my Nuxt project. This particular component contains the following lifecycle hooks: <script> export default { name: 'MyComponent', created() { alert('hello there!') }, ...

How to apply props conditionally in VueJS?

I have a component called blogPost (Component A) that is imported in another component named B. When a button in Component B is clicked, Component A opens in a modal. There are two different use cases for this scenario. 1. One case requires passing 2 prop ...

Ways to verify whether a callback function supplied as a parameter in Javascript has any arguments

My task involves implementing the following: doSomething .then(success) .catch(failure); The success and failure functions are callbacks that will receive their value at runtime (I am developing a module). Therefore, I need to ensure that the fa ...

Approval still pending, awaiting response

Encountering an issue with a POST request using React and Express, where the request gets stuck in the middleware. I am utilizing CRA for the front end and Express JS for the backend. Seeking advice on troubleshooting this problem. Backend server.js var ...

Issue with Material UI React JS Select component: Unable to deselect multiple values when more than one item is selected

Implementing a multiselect dropdown in material ui with specific conditions: The dropdown will contain [0 Apples, 1 Oranges, 2 Grapes]. By default, 0 Apples should be selected. None of the options can be unselected. If 0 Apples is selected and the user se ...

Conceal the countdown clock and reveal the message box

I am attempting to create a functionality where the text box will replace the timer when it reaches 0, and then the timer will be hidden. I am seeking a straightforward solution using either the 'v-show' or 'destroy' property in vue.js ...

I am experiencing an issue in Next.js where the styling of the Tailwind class obtained from the API is not being applied to my

Having an issue with applying a bg tailwind class to style an element using an API. The class text is added to the classlists of my element but the style doesn't apply. Below are the relevant code snippets: //_app.js component import "../index.css"; i ...