Discover the route followed by an object containing a specific key within an array of objects

Imagine having an array of dictionaries like the one below. How can I locate the object with id: 121 using JavaScript? I've been struggling to figure this out and would appreciate any hints or algorithms on how to achieve this.

The desired result should look something like

[{id:1, name:"foo"}, {id: 12, name:"shoo"}, {id: 121, name:"jhj"}]

[
    {
        "id": 1,
        "name": "foo",
        "submenus": [
            {
                "id": 11,
                "name": "bar",
                "submenus": [
                    {
                        "id": 111,
                        "name": "abc"
                    }
                ]
            },
            {
                "id": 12,
                "name": "shoo",
                "submenus": [
                    {
                        "id": 121,
                        "name": "jhj"
                    }
                ]
            }
        ]
    },
    {
        "id": 2,
        "name": "kjk"
    }
]

This is the VueJS code snippet that I came up with:

getBreadcrumbs(menuItems, id, breadcrumbsArray) {
    for (var i = 0; i < menuItems.length; i++) {
      if (menuItems[i].id == id) {
        breadcrumbsArray.push({
          id: menuItems[i].id,
          name: menuItems[i].text
        })
        return breadcrumbsArray
      } else {
        if (menuItems[i].submenus !== 'undefined') {
          if (menuItems[i].submenus.length > 0) {
            console.log('shoo')
            this.getBreadcrumbs(menuItems[i].submenus, id, breadcrumbsArray)
          }
        }
      }
    }
  }

When running this code, it throws the following error:

Error in render: "TypeError: menuItems[i].submenus is undefined"

Answer №1

If you need to achieve a specific requirement, consider defining a recursive function called findPath(). Below are some explanatory notes on how to implement it:

const data=[{"id":1,"name":"foo","submenus":[{"id":11,"name":"bar","submenus":[{"id":111,"name":"abc"}]},{"id":12,"name":"shoo","submenus":[{"id":121,"name":"jhj"}]}]},{"id":2,"name":"kjk"}];

/* Implement a recursive function to locate the path from the root of the dataset to the first matching child with the specified id */
const findPath = (items, id) => {
    
    /* Iterate through the items at this level */
    for(const item of items) {

        if(item.id === id) {
            /* Return an array containing just this item if its id matches */
            return [item]
        }
        else if(Array.isArray(item.submenus)) {
            /* If there are submenus present, recursively search for a nested child with the matching id */
            const result = findPath(item.submenus, id)
            if(Array.isArray(result)) {
                /* Prefix the current item to the results array if a nested child with the id is found */
                return [item].concat(result)
            }
        }
    }
}

/* Map the id and name of each item in the found path to a result array */
const result = findPath(data, 121).map(({ id, name }) => ({ id, name }));

console.log( result );

Additionally, there is a minor error in the way you're checking for the existence of the submenus sub-array in your code.

To resolve this issue, you can make the following adjustment:

getBreadcrumbs(menuItems, id, breadcrumbsArray) {
    for (var i = 0; i < menuItems.length; i++) {
        if (menuItems[i].id == id) {

            breadcrumbsArray.push({
                id: menuItems[i].id,
                name: menuItems[i].text
            });

        } else {

            /* Check if "submenus" is defined using the "typeof" operator */
            if (typeof menuItems[i].submenus !== 'undefined') {
                if (menuItems[i].submenus.length > 0) {
                    this.getBreadcrumbs(menuItems[i].submenus, id, breadcrumbsArray)
                }
            }
        }
    }

    /* Place the return statement here */
    return breadcrumbsArray;
}

To learn more about the typeof operator, refer to this documentation

Answer №2

If you come across a path, grab an object related to the node and add it to the result set.

function findPath(array, target) {
    var path;
    return array.some(({ id, name, submenus = [] }) => {
            if (id === target) return path = [{ id, name }];
            var temp = findPath(submenus, target);
            if (temp.length) return path = [{ id, name }, ...temp];
        })
        ? path
        : [];
}

var array = [{ id: 1, name: "foo", submenus: [{ id: 11, name: "bar", submenus: [{ id: 111, name: "abc" }] }, { id: 12, name: "shoo", submenus: [{ id: 121, name: "jhj" }] }] }, { id: 2, name: "kjk" }];;

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

Answer №3

I've discovered a new method to achieve this task, and I wanted to share my algorithm with you:

  • To begin, conduct a DFS (Depth First Search) on your tree until the node with the corresponding id is located

  • Once the node is found, add it to the breadscrumpArray and return the entire array

  • Each time we explore a submenu element, we can determine whether the desired node is a child of that element or not. If it's not a child, the function getBreadcrumbs will return false

I hope this explanation helps clarify the process. Feel free to ask any questions in the comments section. Cheers!

function getBreadcrumbs(menuItems, id, breadcrumpsArray) {
    for (var i = 0; i < menuItems.length; i++) {
        if (menuItems[i].id == id) {
            // Node found, add it to the array and return
            breadcrumpsArray.push({
                id: menuItems[i].id,
                name: menuItems[i].name
            });
            return breadcrumpsArray;
        } else {
            if (typeof menuItems[i].submenus !== 'undefined') {
                if (menuItems[i].submenus.length > 0) {
                    if (getBreadcrumbs(menuItems[i].submenus, id, breadcrumpsArray)) {
                        // Add the node to the front of the array
                        breadcrumpsArray.unshift({
                            id: menuItems[i].id,
                            name: menuItems[i].name
                        });
                        return breadcrumpsArray;
                    }
                }
            } else {
                // The desired node is not part of this specific path in the tree
                return false;
            }
        }
    }
}

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

Utilizing a library across various files in Node.js

I am looking to integrate Winston for logging in my nodejs express project. Within my main file ( server.js ) I currently have the following code snippet: const winston = require('winston'); winston.level = process.env.LOG_LEVEL winston.log(&ap ...

The console displays "undefined" when formatting API data

I am attempting to format the data retrieved from an API since there is a lot of unnecessary information. However, when I try to display the formatted data in the console, it always shows as "undefined" or "null." I am importing and calling the fetch API ...

In a Vue.js application, there is an issue with missing data in the Axios response headers

I've developed a simple Vue.js application. In my main.js file, I have the following code snippet: import Vue from "vue"; import App from "./App.vue"; import router from "./router/routes"; import store from "./store/root"; import vuetify from "./plug ...

Create a soft focus on the background sans any filters

I am in the process of developing a website and have implemented code to blur out the background: CSS #background{ background: url(img/bg.jpg) no-repeat center center fixed; -webkit-background-size: cover; -moz-background-size: cover; -o ...

Display an array containing date objects in a dropdown menu for users to select from

I am working with an API call that returns an array of objects. Each object in the array contains a date or timestamp in ISO format. Right after my render() method, I have the following code snippet: const pickerItems = this.props.currentData.trips.map(t ...

I'm looking for a solution to implement a vertical carousel in Google's Materialize CSS without the need for custom development

Looking to create a unique vertical scrolling "carousel" using Google's Materialize CSS library. I have a good understanding of the steps required to construct a carousel. # haml %ul.carousel %li.carousel-item Some Content %li.carousel-item ...

To enable RTL in TextField, please note that the JssProvider is only available in "react-jss/src/JssProvider" and not in "react-jss/lib/JssProvider"

Seeking help to convert LTR to RTL in the following code: <TextField id="date" label="EmployeeDate" type="date" onChange= ...

Send key-value pairs to the function using ng-model

I am currently working on a functionality that involves extracting an object from json and displaying its key-value pairs using 'ng-repeat' in AngularJS. The form includes checkboxes where the value can be either true or false, determining if the ...

To dismiss the Div, simply click on any area outside of it. Leveraging the power of SVG, D3

I need a way to hide my div by clicking outside of it. My SVG has a background and a graph with nodes on top of that. I have a special node (circle) on the graph, clicking on which makes a box appear. To show the box, I use the following code: d3.select ...

What is the best way to incorporate jQuery and its plugins into a Vue component?

Is there a way to include jQuery plugins in a Vue application and use them inside the mounted hook? I know that jQuery can be imported via "import" inside a component (in the export default object) and is used in the life-cycle hook called "mounted." Howev ...

Getting a boolean response from an asynchronous SQLite query in Express

I am currently developing a middleware that verifies the validity of a session (meaning it has a logged-in user attached). For this purpose, I am utilizing sqlite3 for node.js. Since I am not very familiar with JavaScript, I am facing some challenges figu ...

Cease the clicking action event

How do I terminate a mousedown function when the mouse is released? $('#manRun').mousedown(function(e3) { var manID = get_id(this); e3.preventDefault(); $(document).on('mousemove.moveMan', function(e2) { ...

Utilizing AngularJS to connect a dynamic result array to a table with varying layouts

I am struggling to bind a dynamic array result with a table using Angular JS in a different layout. Despite multiple attempts, I have not been successful in achieving the desired outcome. Any help or guidance would be greatly appreciated. var arr = [ ...

Using AJAX to retrieve a specific JSON object from an array of JSON data

Data retrieved in JSON array from the API: [{"id":"001", "name":"john", "age":"40"}, {"id":"002", "name":"jane", "age":"30"}] Using Ajax: $.ajax({ url: 'interface_API.php', ...

working with received data from a JavaScript object

Looking for code assistance, I have a data object serving as my data source. var data = [ { "label":"May 7", "value":25736.6, "proID":"ISB" }, // more data objects... ]; I'm manipulating this data to generate another ...

I must eliminate any rows in a table that do not include the specified [string]

I have a task to remove specific rows from a table that do not contain a certain string. $(document).ready(function() { var str = "b"; $("#mytable tr td:not(:contains(str))").parent().remove(); }); //this approach is not produci ...

To prevent the background window from being active while the pop-up is open

I have a link on my webpage that triggers a pop-up window, causing the background to turn grey. However, I am still able to click on other links in the background while the pop-up is open. I tried using the code document.getElementById('pagewrapper&ap ...

Using React Higher Order Components to transmit data attributes to the initial child/element within the encapsulated component

Presently, I have a custom higher-order component structured in the following manner: export const withAttrs = (WrappedComponent) => { const ModifiedComponent = (props) => ( <WrappedComponent {...props} data-test-id="this-is-a-element&q ...

Securing a REST API accessible through JavaScript by implementing authentication techniques due to the visibility of the public code

Inquiry: Need advice on securing an internal API intended for AJAX calls made within the website. I have developed a REST API in PHP 7.2 for use with client-side Javascript. Typically, I work on server-side applications where I can control access using a ...

How can I trigger a click event on a link using JQuery?

One of my links has the unique id: nyhedsklik There is a function associated with this link that activates when it is clicked: $('a.poplight[href^=#]').click(function() { var popID = $(this).attr('rel'); //Fetching Popup ...