Inspect the key within a complex hierarchy of nested objects in an array

I am working with an array of nested objects and need to extract the value of a specific key property. Currently, I am using a for loop and checking for the existence of children property, but I feel there might be a more optimal way to accomplish this task. Below is the array of object data that I am working with, where I need to retrieve the text for the id 121.

var abc = [
  {
    id: 1,
    text: 'One',
    children: [
      {id: 11, text: 'One One'},
      {id: 12, text: 'One two', 
       children: [ {id: 121, text: 'one two one'} ]}
    ]
  },
  {
    id: 2,
    text: 'two'
  }
];

The approach I have implemented seems to be very specific to this particular problem. Here is my current code snippet:

for(var val of abc){

  if(val.id == 121){
    console.log('in first loop',val.text);
    break;
  }

  if(Array.isArray(val.children)){

   for(var childVal of val.children) {
       if(childVal.id == 121){
        console.log('in first child', childVal.text); 
         break;
       }
     if(Array.isArray(childVal.children)){
       for(var nextChild of childVal.children){
         if(nextChild.id == 121){
           console.log('in next child', nextChild.text); 
           break;
         }

       }

       }
   }

  }

}

Answer №1

To retrieve the text property of a matched object, you can utilize a recursive function that utilizes a for...in loop.

var data = [{"id":1,"text":"One","children":[{"id":11,"text":"One One"},{"id":12,"text":"One two","children":[{"id":121,"text":"one two one"}]}]},{"id":2,"text":"two"}]

function getProperty(data, key, value) {
  let result = null;

  for (let i in data) {
    if (typeof data[i] == 'object' && !result) {
      result = getProperty(data[i], key, value);
    }

    if (i == key && data[i] == value) {
      result = data;
    }
  }

  return result;
}

const matchedObject = getProperty(data, 'id', 121);
console.log(matchedObject);

Answer №2

If you're looking for a quick solution, you might consider using a short circuit to retrieve the desired property value.

const
    getProperty = (object, key, id) => {
        const findProperty = obj => {
            if (!obj || typeof obj !== 'object') return;
            if (obj.id === id) return { value: obj[key] };
            let value;
            Object.values(obj).some(prop => value = findProperty(prop));
            return value;
        };
        return findProperty(object)?.value;
    };

var items = [{ id: 1, name: 'Item' }, { id: 2, name: 'Another Item', children: [{ id: 21, name: 'Child Item' }] }];

console.log(getProperty(items, 'name', 21));
console.log(getProperty(items, 'name', 500));

Answer №3

Given a scenario where your Elements contain nested Properties within a children attribute, utilizing recursion along with Array.prototype.find() is the optimal approach to locate a specific Element based on its ID:

const findElementById = (arr, id, childProp = 'children', result) => {
  const search = arr => arr.find(obj => obj.id == id && (result = obj) || childProp in obj && search(obj[childProp]));
  return search(arr) && result;
};

const data = [{id: 1, name: 'Item One', children: [{id: 11, name: 'Child One'}, {id: 12, name: 'Child Two', children: [{id: 121, name: 'Grand Child One'}]}]}, {id: 2, name: 'Item Two' }];
console.log( findElementById(data, 121)?.name ); // Grand Child One

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

Display the Slug in the Website URL upon clicking on a Blog Post using Angular and Strapi framework

When a user clicks on a blog, I want the URL to display the slug instead of the ID. My frontend framework is Angular and I have created a service to fetch data from the backend built with Strapi. Currently, when selecting a blog from the view, the URL disp ...

Generating input fields dynamically in a list and extracting text from them: A step-by-step guide

I am designing a form for users to input multiple locations. While I have found a way to add input boxes dynamically, I suspect it may not be the most efficient method. As I am new to this, I want to ensure I am doing things correctly. Here is how I curren ...

Material UI Snackbar background color not able to be changed

Currently, I'm working on an ErrorHandler component in React.JS that displays a Material UI Snackbar whenever it catches an error. The issue I'm facing is trying to change the background color of the Snackbar to red, which seems to be problematic ...

Incorporating Imported Modules into the Final Build of a Typescript Project

In my Visual Studio Code Typescript project, I have set up some basic configurations and used npm to download libraries. One of the main files in my project is main.ts which includes the following code: import ApexCharts from 'apexcharts' var c ...

The code snippet `document.getElementById("<%= errorIcon.ClientID %>");` is returning a null value

I need to set up validation for both the server and client sides on my registration page. I want a JavaScript function to be called when my TextBox control loses focus (onBlur). Code in the aspx page <div id="nameDiv"> <asp:Upd ...

The tabbing feature in bxslider disrupts the alignment of slides, making it

After encountering accessibility issues, I upgraded the bxslider library to version 4.2.3 for better support. Check out this example of bxslider where you can easily tab through the controls: http://jsfiddle.net/qax7w8vt/2/embedded/result/ The problem a ...

Unable to import a text file using a semicolon as delimiter in d3

I'm just starting to learn JavaScript and the D3 library. I recently explored the "d3-fetch" module (available at https://github.com/d3/d3-fetch) and the d3.dsv command API (find it here: https://github.com/d3/d3-dsv). However, I am struggling to unde ...

Discover how to display the loading time and memory usage of a web page on the footer using the jQuery and AngularJS library

Does anyone know how to display the loading time and memory usage of a web page in the footer using jQuery and AngularJS libraries? I've managed to show the loading time with this jQuery code: <script type="text/javascript"> before = (new Date( ...

Displaying multiple categories of articles on a single page with Node.js

Seeking a solution to limit the number of posts displayed for each category using a .limit() function, but uncertain on how to proceed. Currently utilizing Mongoose and Express in my code setup. The existing code snippet is outlined below: router.get(&a ...

Locate all instances of words that begin with a certain character and are immediately followed by numbers within

I am searching for words that start with "mc" and are followed by digits only. let myString = "hi mc1001 hello mc1002 mc1003 mc1004 mc mca"; Expected output = [mc1001, mc1002, mc1003, mc1004] This is how I tackled it: const myRegEx = /(?:^|\s)mc(. ...

What is the best way to test chained function calls using sinon?

Here is the code I am currently testing: obj.getTimeSent().getTime(); In this snippet, obj.getTimeSent() returns a Date object, followed by calling the getTime() method on that Date. My attempt to stub this functionality looked like this: const timeStu ...

Disappearing markers issue in Openlayers when zooming

I am trying to ensure that markers on the map do not get erased when zooming in or out. Here is my script: JS $(document).ready(function() { //initialization var map; var markerPosition; // Marker position var options = { restrictedE ...

Is there a way for me to receive the response from the this.$store.dispatch method in vue.js 2?

Here is the structure of my component : <script> export default{ props:['search','category','shop'], ... methods: { getVueItems: function(page) { this.$store.disp ...

Retrieve data from two separate files and store it as a two-dimensional array in JavaScript

Is there a way to read and convert two .txt files into a 2d array? I currently have a code snippet that looks like this : var fs = require('fs') file = './text1.txt' fs.readFile(file,'utf-8', (e,d) => { textByLine = d.s ...

Trigger a jQuery click event to open a new tab

On a public view of my site, there is a specific link that can only be accessed by authenticated users. When an anonymous user clicks on this link, they are prompted to log in through a popup modal. To keep track of the clicked link, I store its ID and inc ...

Tips for incorporating user-entered data from a text box into a JavaScript function and utilizing a loop

Although my code is functioning correctly, I am looking to make some adjustments but seem to be struggling to achieve the desired outcome. Essentially, I have two labels and an input field in which the user is prompted to enter a specific number of weeks ...

Separate mathematical expressions into an array without breaking apart any subexpressions inside parentheses or single quotes

Consider this given string: 1 + 2 * (3 + (23 + 53 - (132 / 5) + 5) - 1) + 2 / 'test + string' - 52 The task is to divide the string into an array of operators and non-operators, while preserving the content between () and '. The desired ou ...

"Optimizing reload time for DIV content with jQuery's .load function is proving to be

I am currently facing an issue with a div that displays data from a database and a form that updates item quantities. After submitting the form, the div refreshes while a modal with a bootstrap spinner pops up to indicate it is loading. The problem arises ...

Ways to prevent negative values from appearing in the text field

Check out this code snippet on Fiddle. I need help with a text field that should only display positive values. If the input is negative, I want it to be stored in ng-model but not shown in the textbox. function LoginController($scope) { $scope.number = ...

Generating JSON data with Ruby for a collection of items

I'm a beginner with Ruby. My goal is to generate a JSON file for a set of elements. To achieve this, I am utilizing the each function to fetch the data. The desired structure of the JSON file for a 4 element array is as follows: '{ "desc" ...