当前位置: 首页 > 知识库问答 >
问题:

如何递归查找嵌套对象中值的键

闻人锦
2023-03-14

我想在一个带有递归的Javascript嵌套对象中找到一个值的键。

下面是我对函数的尝试。有没有更优雅的方法来实现这一点?

null

const foo = { data: { data2: { data3: 'worked' }, data21: 'rand' }, data01: 'rand01' }

function findKey(obj, target) {
  let result = null;
  if (_.isEmpty(obj) || !_.isObject(obj)){
    return null;
  }
  if (!_.isArray(obj) && Object.keys(obj).length > 0) {
    for(let i=0; i < Object.keys(obj).length; i++){
      let key = Object.keys(obj)[i];
      let val = obj[key];
      if (val === target) {
        return key;
      }else{
        result = findKey(val, target);
      }
      if (result) {break}
    }
  }
  return result;
}
console.log(findKey(foo, 'worked'))
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

null

例如,有没有一种方法可以避免检查result的值然后中断?我觉得result应该能够在调用堆栈中冒泡,直到它在第一次函数调用时返回,而不必中断。

共有1个答案

王棋
2023-03-14

在上面提出的几个问题之后,该函数看起来应该:

  • 假设输入始终是对象。
  • 假设它可能会以它的方式遇到数组。
  • 假设在满足一个值后必须停止(如果存在多个值)。

OP提供的输入代码不处理数组情况。

对以下代码进行了采样,以便使用这些示例案例:

  • 嵌套对象结构。
  • 对象或元素的嵌套数组。

Below函数接受第二个参数,这是一个回调,用于评估met元素是否是我们要查找的元素。这样,处理更复杂的检查就更容易了。

保留递归方法,一旦满足键,函数只需return,以避免不必要的搜索。

null

const foo = { data: { data2: { data3: 'worked' }, data21: 'rand' }, data01: 'rand01' };
const fooWithArrays = {
  data: {
    data2: {
      data3: 'not here'
    },
    data4: [
      { data5: 'worked' },
      { data6: 'not me' }
    ]
  }
};
const fooWithExpression = {
  data: {
   data2: {
    data3: { id: 15, name: 'find me!' }
   },
   data21: {
    data25: 'not me'
   }
  }
};

const findKeyByValue = (obj, equalsExpression) => {
  // Loop key->value pairs of the input object.
  for (var [key, v] of Object.entries(obj)) {
    // if the value is an array..
    if (Array.isArray(v)) {
      // Loop the array.
      for (let i = 0; i < v.length; i++) {
        // check whether the recursive call returns a result for the nested element.
        let res = findKeyByValue(v[i], equalsExpression);
        // if so, the key was returned. Simply return.
        if (res !== null && res !== undefined) return res;
      }
    }
    // otherwise..
    else {
      // if the value is not null and not undefined.
      if (v !== null && v !== undefined) {
        // if the value is an object (typeof(null) would give object, hence the above if). 
        if (typeof(v) === 'object') {
          // check whether the value searched is an object and the match is met.
          if (equalsExpression(v)) return key;
          // if not, recursively keep searching in the object.
          let res = findKeyByValue(v, equalsExpression);
          // if the key is found, return it.
          if (res !== null && res !== undefined) return res;
        }
        else {
          // finally, value must be a primitive or something similar. Compare.
          let res = equalsExpression(v);
          // if the condition is met, return the key.
          if (res) return key;
          // else.. continue.
        }
      }
      else continue;
    }
  }
}

console.log( findKeyByValue(foo, (found) => found === 'worked') );
console.log( findKeyByValue(fooWithArrays, (found) => found === 'worked') );
console.log( findKeyByValue(fooWithExpression, (found) => found && found.id && found.id === 15) );
 类似资料:
  • 问题内容: 我试图找出如何递归地在此JSON对象中搜索节点。我尝试了一些但无法获得的东西: 这是我无法使用的解决方案,可能是因为当子节点在数组中时,第一个节点只是一个值: 问题答案: 您的代码只是缺少一个循环来检查数组中节点的每个子节点。此递归函数将返回节点的属性,或者如果树中不存在标签,则返回该属性: 您还可以使用显式堆栈进行迭代,该堆栈更快,更凉爽并且不会导致堆栈溢出:

  • 我有一个LOCATION实体,它包含国家、州和城市。并且我有一个LocationRepository接口定义为: 我想按国家找到所有的州。我可以遵循方法名称标准来查询位置实体的所有内容。如果我想要列表,我需要创建StateRepository接口并在其中查询关于状态的一切吗?如果我可以从LocationRepository中获取它,那么方法是什么样子的?我假设它看起来会像下面这样(当然不起作用)。

  • 问题内容: 我正在使用有角JS及其示例之一:http : //jsfiddle.net/furf/EJGHX/ 在发送更新功能之前,我需要获取数据并向其中添加一些值。(如果用angular而不是js更好,请告诉我) 我正在尝试获取“父代”和“索引”并更新子代。 这是我正在遍历的数据 这就是我目前正在遍历的方式,但是它只能得到第一个维度 我在另一个小提琴上找到了这个,但我不知道该如何抓取父对象或索引

  • 问题内容: 我正在尝试从JSON对象动态构建表单,该对象包含表单元素的嵌套组: 我一直在使用ng-switch块,但是它与嵌套项变得站不住脚,就像上面的Address对象一样。 这是小提琴:http : //jsfiddle.net/hairgamiMaster/dZ4Rg/ 关于如何最好地解决此嵌套问题的任何想法?非常感谢! 问题答案: 我认为这可以为您提供帮助。它来自我在Google网上论坛上

  • 问题内容: 我使用此代码从Jhonny的Question中的json 对象中找到了所需的部分 数据样本 查找功能 像这样使用: 此代码是从源代码中选择匹配的片段。但是我想要的是用新值更新源对象并检索更新的源对象。 我想要类似的东西 我的密码 如果我给定但如果我将代码更改为未定义的更新,则此方法有效。 为什么呢? 问题答案: 您忘记在嵌套调用中传递newValue

  • 问题内容: 我在下面的对象中尝试获取所有id值。 使用以下代码,我仅获得第一个id值。有没有办法从嵌套对象中获取所有id值,而无需使用任何外部模块。 预期产量 问题答案: 您可以使用如下所示的JavaScript函数来获取嵌套属性: 检查此小提琴以获取可行的解决方案。