quickest method for retrieving a property by name, regardless of its location within the object hierarchy

I am looking for a solution to retrieve the value of a property from an object graph, and I am wondering if there is a more efficient alternative to the method I have outlined below.

Instead of using recursion, I have chosen tree traversal because it conserves stack frames and memory, and it is also faster.

For example:

const obj = {someObj:{}, someOtherObj: {nestedObjet: {featureRole: "canary"}}}
const prop = findProperties(obj, "featureRole");
console.log(prop); //canary
  • Breadth First Search of Properties

findProperty(obj: Record<string, any>, propId: string): any {
    if (obj && obj[propId] != undefined) {
        return obj[propId];
    }
    const props = [obj];
    while (props.length) {
        const prop = props.shift();
        if (typeof prop === 'object') {
            if (prop && prop[propId] != undefined) {
                return prop[propId];
            }
            for (const innerProp in prop) {
                if (Object.prototype.hasOwnProperty.call(prop, innerProp) && typeof prop[innerProp] === 'object') {
                    props.push(prop[innerProp]);
                }
            }
        }
    }
}

Answer №1

If you want to achieve this recursively, one approach is to either return as soon as a value is found:

const obj = {
  someObj: {}, someOtherObj: { nestedObjet: { featureRole: "canary" } },
  obj: { someOtherObj: { nestedObjet: { featureRole: "cockatoo" } }
}

const findProperties = (obj, prop) => {
  if (obj[prop] !== undefined) {
    return obj[prop];
  }
  for (const key in obj) {
    if (typeof obj[key] === 'object') {
      const res = findProperties(obj[key], prop);
      if (res !== null) {
        return res;
      }
    }
  }
  return null;
}

const prop = findProperties(obj, "featureRole");
console.log(prop); //canary

Alternatively, you can collect all the possible matches:

const obj = {
  someObj: {}, someOtherObj: { nestedObjet: { featureRole: "canary" } },
  obj: { someOtherObj: { nestedObjet: { featureRole: "cockatoo" } }
}

const findProperties = (obj, prop, res = []) => {
  if (obj[prop] !== undefined) {
    res.push(obj[prop]);
  }
  for (const key in obj) {
    if (typeof obj[key] === 'object') {
      findProperties(obj[key], prop, res);
    }
  }
  return res;
}

const prop = findProperties(obj, "featureRole");
console.log(prop); // ["canary", "cockatoo"]

Answer №2

Here is a solution with specific constraints such as using \" in property name/value:

searchAttributes = (obj, attribute) => JSON.stringify(obj).match(new RegExp(`"\(${attribute}\)":"\([^"]*\)"`, 'gi')).map(match => match.split(':').map(str => str.replace(/"/gi, '')));

How to Use:

searchAttributes(someObject, "attributeName").map(([,value]) => console.log(value));

Answer №3

Employing recursion is a powerful approach to navigate through your object.

const object = {
  a: {
   d: 24
  },
  b: {
    e: 5,
    f: {
        g: 'B'
    }
  },
  c: 12
};

function getProp(object, propName) {
  if (propName in object) {
    return object[propName];
  } else {
    for (const prop in object) {
      if (typeof object[prop] === 'object') {
        const results = getProp(object[prop], propName);
        if(!!results) {
          return results;
        }
      }
    }
  }
}

Feel free to experiment with it here: https://jsfiddle.net/tpbhexgw/10/

Answer №4

Presented below is a methodical approach utilizing object-scan.

This tool is meticulously engineered for swiftness, employing iteration over recursion internally.

// const objectScan = require('object-scan');

const obj = { someObj: {}, otherObj: { some: { deep: { nested: { key: {} } } }, someOtherObj: { nestedObjet: { featureRole: 'canary' } } };

// prepare search function (single-time operation)
const searchFn = objectScan(['**.featureRole'], { abort: true, rtn: 'bool' });

// perform search
console.log(searchFn(obj));
// => true
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="523d30383731267f2131333c1263667c627c62">[email protected]</a>"></script>

Disclaimer: The author of object-scan

While this approach may not surpass the speed of crafting your own iterative solution, it offers the benefit of trimming the search tree if additional metadata regarding key positions is provided.

For instance, if you are aware that the key resides precisely one or two levels deep, you could implement the following to limit the search depth

// const objectScan = require('object-scan');

const obj = { someObj: {}, otherObj: { some: { deep: { nested: { key: {} } } } }, someOtherObj: { nestedObjet: { featureRole: 'canary' } } };

const searchFn = objectScan(['{*,*.*}.featureRole'], { abort: true, rtn: 'bool' });

console.log(searchFn(obj));
// => true
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f49b969e919780d98797959ab4c5c0dac4dac4">[email protected]</a>"></script>

Disclaimer: The author of object-scan

Such modifications often yield a more significant impact compared to minutely refining code (which could be altered by a different compiler with unpredictable outcomes).

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

Struggling with deploying Next.js on Vercel

Encountered an issue while trying to deploy a project on Vercel. The error message is as follows: fileName: comps/Navbar.js imported as import Navbar from "./Navbar"; 16:36:51 ModuleNotFoundError: Module not found: Error: Can't reso ...

Executing an SQL delete query with a button click using a JavaScript function in PHP

I have created a setup with three essential files - index.html, database.php, and function.js. In database.php, there is a form generated containing a delete button that triggers the deletion SQL query when clicked. The primary objective is to present a ta ...

"Learn the trick of converting a stream into an array seamlessly with RxJs.toArray function without the need to finish the

In order to allow users to filter data by passing IDs, I have created a subject that can send an array of GUIDs: selectedVacancies: Subject<string[]> = new Subject(); selectedVacancies.next(['a00652cd-c11e-465f-ac09-aa4d3ab056c9', ...

Encountering issues while retrieving date data from Firebase in Angular 6

this.qS = this.afDatabase.list('path', ref => { return ref.limitToLast(1000); }).snapshotChanges().map(changes => { return changes.map(c => ({ key1: c.payload.key,value1:c.payload.val() })); }); this.qS.subscribe(values =&g ...

Obtain the result of the Mongoose find operation

Greetings, I am facing a challenge with accessing elements returned from a find operation in Mongoose due to the asynchronous nature and callback functions. Below is the code for reference: function retrieveBudgets(email, callback) { models.User.f ...

The $route.reload() function seems to be ineffective in Internet Explorer

I'm currently using AngularJs to develop an application. The issue I am encountering is related to data not being refreshed in IE, even after executing the $route.reload() function. Strangely enough, this problem only occurs in Internet Explorer and w ...

Node.js user update complete

I am currently working on enabling users to edit their profiles. However, the code I have set up does not seem to be functioning as expected. The form I am using looks like this: <form action="/dashboard/users/edit/:id" method="put"> And my route ...

AngularJS 500 server error

In my current project, I am developing a straightforward angularjs - J2EE application that fetches data from a mysql server and then displays it on an HTML page. The angular function is triggered on form submission as shown below: <div id="register_for ...

Angular 4 is displaying an error message indicating that the expression has been modified after being initially verified

I've been utilizing Angular Material within my Angular 4 application. There seems to be an issue when attempting to utilize the MatSnackBar in the ngAfterViewInit(). The error I encounter is as follows: ExpressionChangedAfterItHasBeenCheckedError: ...

Drag and Drop Feature using Angular with JQuery UI for Cloning Elements

I've been working on a web design project where I want to create a draggable user interface. https://i.sstatic.net/Be0Jk.png The goal is for users to click and drag different types of questions from the left side to the right side of the screen. Cu ...

Ensure that an async function's result is resolved before rendering react routes

I've been working on setting up an authentication service in my single-page application using React in the routes file. The goal is to check if a user is trying to access a private path, and verify that the token stored locally is valid. However, I&ap ...

Protecting a javascript string in php: A comprehensive guide

Having trouble with my PHP javascript string. Attempted to add a string to a variable within a switch statement but encountered an error: $blocPub = '<script type="text/javascript"> var rdads=new String(Math.random()).substring (2, 11 ...

Utilize viewport activation to determine browser width

Is there a way to dynamically add the viewport-meta tag only for devices with screen widths larger than 680px? If the screen is smaller than 680px, then the responsive style file should be enabled instead. I attempted to achieve this by placing the follow ...

What is the best way to retrieve the input value from post.ejs?

app.js var express = require('express'); var bodyParser = require('body-parser'); var app = express(); var passport = require('passport'); var localStrategy = require('passport-local'); var axios = require("axi ...

Creating dynamic forms with JQuery and ReactJS

I have been tasked with creating a form-builder that will be integrated into an application. My role is to focus on designing the front-end using ReactJS. The client’s requirements are very similar to the features of the "jQuery Form-Builder," so I decid ...

Sending data from an AJAX request to a Spring controller is a common task in web

var TableDatatablesEditable = function () { var handleTable = function () { function restoreRow(oTable, nRow) { var aData = oTable.fnGetData(nRow); var jqTds = $('>td', nRow); for (var i = 0, ...

When I click a button in d3 to refresh the data on my bar graph, the text fails to update accordingly

I've successfully created a series of data lists that modify the bargraph. Unfortunately, due to their differing x and y values, they end up printing new values on top of existing ones. Shown below is an image illustrating the issue where x and y val ...

Refreshingly modernizing SVG in Angular

I've been facing a challenge in my Angular application where I am trying to dynamically add paths to an SVG element within an HTML file. The issue is that even though the paths are getting added to the DOM, they are not showing up in the browser when ...

Implementing ID-based filtering for an array of objects with React

Struggling with filtering an object in an array of objects by its ID using React. Here's the scenario: The app is a Notes app that stores each note with its Title, Text, and created date, utilizing the ID as the key. Currently, I'm working on c ...

What is the method to assert that two arguments are equal within a function?

When working with TypeScript, you can pass a value to a function and have that function assert the value is true for type narrowing. For example: function assertTrue(v: unknown, message: string): asserts v { if (!v) { throw new MySpecialError(message ...