Removing the main node from the tree of structured information

I have retrieved a list of menus from the database, labeled "sample," shown below:

[
  { id: 1, name: 'Main Menu', branch: 1, subbranch1: 0, subbranch2: 0 },
  { id: 2, name: 'Main Menu 2', branch: 2, subbranch1: 0, subbranch2: 0 },
  { id: 3, name: 'Sub Menu 1-1', branch: 1, subbranch1: 1, subbranch2: 0 },
  { id: 4, name: 'Sub Menu 1-2', branch: 1, subbranch1: 2, subbranch2: 0 },
  { id: 5, name: 'Sub Menu 1-2-1', branch: 1, subbranch1: 2, subbranch2: 1 },
  { id: 6, name: 'Sub Menu 2-1', branch: 2, subbranch1: 1, subbranch2: 0 },
  { id: 7, name: 'Sub Menu 2-2', branch: 2, subbranch1: 2, subbranch2: 0 },
]

Each menu in this list is assigned values for branch, subbranch1, and subbranch2 which determine its position in the menu hierarchy. A menu can act as a clickable item or serve as a group heading for other menus (essentially acting as a parent).

For instance, Menu with id 1 has submenus 3 and 4 under it as subbranch1, and Menu with id 4 has submenu 5 under it as subbranch2.

I am seeking to identify all the menus that do not have any children (in other words, they are clickable menus rather than group menus).

The final result for the "given sample" should be:

 [
  { id: 3, name: 'Sub Menu 1-1', branch: 1, subbranch1: 1, subbranch2: 0 },
  { id: 5, name: 'Sub Menu 1-2-1', branch: 1, subbranch1: 2, subbranch2: 1 },
  { id: 6, name: 'Sub Menu 2-1', branch: 2, subbranch1: 1, subbranch2: 0 },
  { id: 7, name: 'Sub Menu 2-2', branch: 2, subbranch1: 2, subbranch2: 0 },
]

Answer №1

To obtain the deepest nodes, start by creating the tree structure and then extract only the nodes located at the maximum depth.

  1. Create the tree

    • Compile all level keys into an array for easy iteration.
    • Traverse through all nodes and construct nested objects for each nested node discovered.
    • Assign the node to the property _.
  2. Identify deepest nodes

    • Retrieve the keys of the object.
    • Iterate through the keys.
      • Check if the key is _, then exit the current iteration.
      • Determine if the property contains a single key and that the key is _; this indicates the deepest node has been found. Extract the underscore property for the node collection and break out of the loop.
      • If not, attempt to locate the deepest node within the current key.
  3. Provide the final result.

function getDeepestNodes(nodes) {

    function getDeepest(node) {
        Object.keys(node).forEach(function (key) {
            if (key === '_') {
                return;
            }
            if (Object.keys(node[key]).length === 1 && '_' in node[key]) {
                result.push(node[key]._);
                return;
            }
            getDeepest(node[key]);
        });
    }

    var levels = ['branch', 'subbranch1', 'subbranch2'],
        tree = Object.create(null),
        result = [];

    nodes.forEach(function (node) {
        var temp = tree;
        levels.every(function (level, i, ll) {
            temp[node[level]] = temp[node[level]] || {};
            temp = temp[node[level]]
            return node[ll[i + 1]];
        });
        temp._ = node;
    });

    getDeepest(tree);

    return result;
}

var data = [{ id: 1, name: 'Main Menu', branch: 1, subbranch1: 0, subbranch2: 0 }, { id: 2, name: 'Main Menu 2', branch: 2, subbranch1: 0, subbranch2: 0 }, { id: 3, name: 'Sub Menu 1-1', branch: 1, subbranch1: 1, subbranch2: 0 }, { id: 4, name: 'Sub Menu 1-2', branch: 1, subbranch1: 2, subbranch2: 0 }, { id: 5, name: 'Sub Menu 1-2-1', branch: 1, subbranch1: 2, subbranch2: 1 }, { id: 6, name: 'Sub Menu 2-1', branch: 2, subbranch1: 1, subbranch2: 0 }, { id: 7, name: 'Sub Menu 2-2', branch: 2, subbranch1: 2, subbranch2: 0 }],
    result = getDeepestNodes(data);

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

Answer №2

This intricate nested loop testing structure presents a challenge. Simplifying the process would involve each line referencing the id of its immediate parent menu, making iteration and testing much easier. The assumed menu structure is as follows:

+-------------+
|  Main Menu  |
+-------------+
  +--------------+
  | Sub Menu 1-1 |
  +--------------+
  | Sub Menu 1-2 |
  +--------------+
    +----------------+
    | Sub Menu 1-2-1 |
    +----------------+
+-------------+
| Main Menu 2 |
+-------------+
  +--------------+
  | Sub Menu 2-1 |
  +--------------+
  | Sub Menu 2-2 |
  +--------------+

To tackle this issue, a possible solution could be implemented like so:

old=<original array>
new= new array()
for (z=0;z<old.length;z++) // Iterating through each line
{
    linkonly = 1 // To prevent multiple 
    if (old[z].subbranch2 == 0) // No sub menu for 3rd level
    {
        for (y=0;y<old.length;y++) // Iterating through each line
        {
            if (z!=y )  // Avoid checking against itself
            {
                if (old[z].branch == old[y].branch) // Matching main branches
                {
                    if (old[z].subbranch1 != 0) // If submenu, continue
                    {
                        if (old[z].subbranch1 == old[y].subbranch1) // Same submenu section
                        {
                            if (old[y].subbranch2 != 0) // Submenu of tested parent
                            {
                                linkonly = 0
                                y=old.length
                            }
                        }
                    }else{
                        if (old[y].subbranch1 != 0) // Submenu of tested item
                            linkonly = 0
                            y=old.length
                        {
                    }
                }
            }
        }
    }
    if (linkonly == 1)
    {
        // push line into new array
    }
}
// utilize new array

A more effective approach would be to transform the initial data structure into something like this:

[
  { id: 1, name: 'Main Menu', parent:0, pos:1 },
  { id: 2, name: 'Main Menu 2', parent:0, pos:2 },
  { id: 3, name: 'Sub Menu 1-1', parent:1, pos:1 },
  { id: 4, name: 'Sub Menu 1-2', parent:0, pos:2 },
  { id: 5, name: 'Sub Menu 1-2-1', parent:4, pos:1 },
  { id: 6, name: 'Sub Menu 2-1', parent:2, pos:1 },
  { id: 7, name: 'Sub Menu 2-2', parent:2, pos:2 },
]

This structure enables testing like this:

old=<original array>
new= new array()
for (z=0;z<old.length;z++) // Looping through each line
{
    linkonly=1
    for (y=0;y<old.length;y++) // Looping through each line
    {
        if (x!=y) // Avoid self-testing
        {
            if (old[y].parent == old[x].id)
            {
                linkonly=0
                y=old.length
            }
        }
    }
    if (linkonly == 1)
    {
        // push line into new array
    }
}
// utilize new array

An alternate method involves loading lines in a multi-dimensional array and iterating through them to identify the presence of sub menus by analyzing the sub-array.

Answer №3

  function determineClickableMenu(menu, menus){
    let branchCount;
    let subbranch1Count;
    if(menu.subbranch1 === 0){
      branchCount = menus.reduce((acc,m)=>{
        return m.branch === menu.branch ? acc + 1 : acc;
       },0);
      return branchCount === 1;
    }
    if(menu.subbranch2 === 0){
       subbranch1Count = menus.reduce((acc, m)=>{
          return (m.subbranch1 === menu.subbranch1 && m.branch === menu.branch) ? acc + 1 : acc;
       }, 0);
       return subbranch1Count === 1;
    }
    return true
  }

  function findClickableMenus(menus){
    const clickableArray = [];
    for (let i = 0; i < menus.length; i++) {
      if(determineClickableMenu(menus[i], menus)){
       clickableArray.push(menus[i]);
      }
    }
    return clickableArray;
  }
  
  const menus = [
    { id: 1, name: 'Main Menu', branch: 1, subbranch1: 0, subbranch2: 0 },
    { id: 2, name: 'Main Menu 2', branch: 2, subbranch1: 0, subbranch2: 0 },
    { id: 3, name: 'Sub Menu 1-1', branch: 1, subbranch1: 1, subbranch2: 0 },
    { id: 4, name: 'Sub Menu 1-2', branch: 1, subbranch1: 2, subbranch2: 0 },
    { id: 5, name: 'Sub Menu 1-2-1', branch: 1, subbranch1: 2, subbranch2: 1 },
    { id: 6, name: 'Sub Menu 2-1', branch: 2, subbranch1: 1, subbranch2: 0 },
    { id: 7, name: 'Sub Menu 2-2', branch: 2, subbranch1: 2, subbranch2: 0 },
  ];
  
  console.log(findClickableMenus(menus));

Great solution uncovered!.. possibly some fine-tuning can be done for optimization

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

Converting to JSON format by utilizing MemoryStream and including line breaks in C#

My objective is to convert C# class data into JSON format using a MemoryStream and DataContractJsonSerializer. MemoryStream stream1 = new MemoryStream(); DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person)); ser.WriteObject(stre ...

Managing the orientation of the print grid panel in ext.net

I have a grid panel on my webpage with a toolbar that includes a print button to print the content of the grid view. The layout direction of the grid is set from Right to Left (RTL) to accommodate Arabic text. However, when I click on the print button, th ...

Exploring the Functionality of Chaining in JQuery and Understanding its Inner Workings

I have a question and I am looking for the best answer. Hopefully, someone in our group can provide it. Most of you are familiar with jQuery chaining. It allows us to attach multiple events to an HTML element using just one statement. For example: $(&ap ...

Optimizing JSON Data Structure Efficiency: Best Practices for Converting JSON to Objects

Struggling with the design of my web application involving JSON, ASP.NET, TypeScript/JavaScript, and AngularJS. In Brief: Seeking best practices for transmitting data from server to client via JSON, utilizing the JSON string on the client side to generate ...

Even after being removed from the DOM using Ajax load, JQuery continues to execute

Currently, within my Laravel 5.2 single page application development, I am faced with the following issue. I have an add.blade.php file and an edit.blade.php file, both containing a script with the same class name and id. When I use .load to load add.blade ...

I am experiencing difficulty with jQuery connecting to the elements on my server-generated webpage

My issue lies in using jQuery functionality within the Software AG webMethods IDE, where pages are generated automatically. I am providing jQuery's functions with a server-generated element ID, but it seems that jQuery is unable to interact with it - ...

Initiate the function one time

The Introduction: I need assistance with a form that triggers a jQuery function when a button is clicked. The issue arises after the initial execution, as the function continues to run one more time. My dilemma is figuring out how to ensure that the funct ...

Creating a dynamic configuration for service instantiation in Angular 4/5

Currently working on a library that has an AuthModule with an AuthService for managing OAuth2 authentication using oidc-client-js. I want the application using this library to be able to set up the configuration for the OAuth client. One way to do this is ...

AngularJS - ng-repeat not updating when property array changes

I have a loop in my HTML using ng-repeat: <div class="row"> <div ng-repeat="item in model.painel track by item.codigoIncidente"> <strong>{{item.restante.horaMinutoSegundo}}</strong> </div> </div> In ...

What is the method in MySQL to convert a VARCHAR to an UNSIGNED type within a JSON_OBJECT?

Consider a scenario where there is a table with two columns, A and B, both of type VARCHAR: |------------|-------------| | A | B | |------------|-------------| | EMPLOYEE | 34 | |------------|-------------| | OTHER | my ...

What is the best way to update the page based on the user input from a prompt?

In my previous question, I was instructed to convert my variables into strings, which I did. However, despite making these changes, the code is still not functioning as intended. The purpose of this code is to prompt the user to select a mood from 1-10, wi ...

What is the best method for generating a large number of Express.js routes quickly and efficiently?

Is there a way to efficiently generate multiple routes in Express? I am looking to create routes in the format localhost:3000/${insert address here} Should I use a for loop or is there a built-in feature in Express that can help with this? For instance, ...

Issue with generating JSON response in CakePHP version 2.x

Having an issue with providing a JSON encoded response from a PHP array in my Cake 2.x application. Set up routing for JSON extension in app/Config/routes.php using Router::parseExtensions('json'); In the Controller, I have: public function aj ...

Create engaging animations using JavaScript to draw moving circles on an

I'm attempting to achieve a seamless animation of a moving circle from one set of coordinates to another. In this particular scenario, the circle moves from (10, 10) to (50, 50). Below you can find the code for my Bullet class. Whenever the user press ...

Problem encountered in NextJS/ReactJS when attempting to dynamically load a new component by clicking a button within the current component

In my NextJS project, I am working with 3 components named "Sidebar", "Woven", and "ToolsPage". Below are the respective codes for each: ToolsPage Component: "use client" import Woven from './components/weaved'; import Sidebar from &ap ...

Tips for sending a JSON object with an embedded array

I have a jquery function that I need to use to post an object to the controller. Everything is working fine except for the ListOfCBToDisplay, which is a list. <script> function Submit_Movie() { // var title = $('[id*="Title"]') ...

The operation could not be completed with exit code 1: executing next build on Netlify platform

Having trouble deploying my Next.JS site to Netlify due to a build error. The site was working fine previously. Any suggestions on how to resolve this issue? 3:43:14 PM: - info Generating static pages (2/6) 3:43:14 PM: - info Generating static pages (4/6) ...

How to use Yii2 to trigger a controller action from a view and effectively debug the

Within a data grid view, there is a text input field where I intend to trigger a controller function when the field is updated. To achieve this, I have embedded a script in my form and set up a controller function. $this->registerJs( "$('#prod ...

Experiencing difficulties when establishing a connection between MongoDB and Node.js

I'm encountering an issue when attempting to connect MongoDB and Node.js on my local server. Can anyone assist me with solving this problem? Below is my JavaScript code: const mongodb = require("mongodb"); // Provide the function to connect to the d ...

Best practices for efficiently utilizing setInterval with multiple HTTP requests in NodeJS

Imagine you have a collection with 3 to 5 URLs. You want to send requests every 5 seconds, one by one. Here is how I approached this: setInterval(() => { array.forEach(element => { request .get(element.url) .on('response', ...