繁体   English   中英

如果属性存在于 object 图中的任何位置,则按名称获取属性的最快方法

[英]fastest way to get a property by name if it exists anywhere in the object graph

如果属性值存在于 object 图中的任何位置,我希望能够检索该属性的值,并且我想知道是否有更快的方法来实现我在下面提出的选项。

我特别选择了树遍历而不是递归,因为它使用更少的堆栈帧和 memory 并且因为遍历更快。

例子:

const obj= {someObj:{}, someOtherObj: { nestedObjet: {featureRole: "canary"}}}
const prop= findProperties(obj, "featureRole");
console.log(prop); //canary
  • 广度优先搜索属性
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]);
          }
        }
      }
    }

您可以递归地执行此操作,或者在找到值后立即返回:

 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

或收集所有可能的匹配项:

 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"]

具有一些限制的解决方案,例如属性名称/值中的\"

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

用法:

findProperties(obj, "featureRole").map(([,v]) => console.log(v));

您可以使用递归在 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;
        }
      }
    }
  }
}

你可以在这里玩: https://jsfiddle.net/tpbhexgw/10/

这是使用object-scan的迭代解决方案。

这个库是为了速度而从头开始构建的。 它在内部使用迭代而不是递归。

 // const objectScan = require('object-scan'); const obj = { someObj: {}, otherObj: { some: { deep: { nested: { key: {} } } } }, someOtherObj: { nestedObjet: { featureRole: 'canary' } } }; // compile search function (only needs to be done once) const searchFn = objectScan(['**.featureRole'], { abort: true, rtn: 'bool' }); // execute search console.log(searchFn(obj)); // => true
 .as-console-wrapper {max-height: 100%;important: top: 0}
 <script src="https://bundle.run/object-scan@14.0.0"></script>

免责声明:我是对象扫描的作者

虽然这不会比编写自己的迭代解决方案快,但它的主要优点是,如果您有任何其他关于密钥 position 的元信息,它将修剪搜索树。

例如,如果您知道密钥恰好位于一两个嵌套深度,您可以编写以下内容,它永远不会搜索比这更深的

 // 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/object-scan@14.0.0"></script>

免责声明:我是对象扫描的作者

这类更改通常比微优化代码具有更大的影响(不同的编译器可能会做谁知道无论如何)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM