Javascript 对象递归以在最深层查找项目 [英] Javascript object recursion to find an item at the deepest level

查看:82
本文介绍了Javascript 对象递归以在最深层查找项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试递归搜索包含字符串、数组和其他对象的对象,以在最深层找到一个项目(匹配一个值),但是我总是得到 undefined 作为返回结果.我可以通过一些控制台日志看到我正在找到该项目,但它被覆盖了.知道我哪里出错了吗?

I'm trying to recursively search an object that contains strings, arrays, and other objects to find an item (match a value) at the deepest level however I'm always getting undefined as the return result. I can see through some console logging that I am finding the item but it gets overwritten. Any idea where I'm going wrong?

  var theCobWeb = {
    biggestWeb: {
      item: "comb",
      biggerWeb: {
        items: ["glasses", "paperclip", "bubblegum"],
        smallerWeb: {
          item: "toothbrush",
          tinyWeb: {
            items: ["toenails", "lint", "wrapper", "homework"]
          }
        }
      },
      otherBigWeb: {
        item: "headphones"
      }
    }
  };

  function findItem (item, obj) {
  var foundItem;
  for (var key in obj) {
    if (obj[key] === item) {
      foundItem = obj;
    } else if (Array.isArray(obj[key]) && obj[key].includes(item)) {
      foundItem = obj;
    } else if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
      findItem(item, obj[key]);
    } 
  }
      return foundItem;
}

var foundIt = findItem('glasses', theCobWeb);
console.log('The item is here: ' + foundIt); // The item is here: undefined 

根据下面的反馈稍微清理了代码.

cleaned up the code a bit based on feedback below.

推荐答案

function findItem (item, obj) {
  for (var key in obj) {
    if (obj[key] === item) { // if the item is a property of the object
      return obj;            // return the object and stop further searching
    } else if (Array.isArray(obj[key]) && obj[key].includes(item)) { // if the item is inside an array property of the object
      return obj;            // return the object and stop the search
    } else if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) { // if the property is another object
      var res = findItem(item, obj[key]); // get the result of the search in that sub object
      if(res) return res; // return the result if the search was successful, otherwise don't return and move on to the next property
    } 
  }
  return null; // return null or any default value you want if the search is unsuccessful (must be falsy to work)
}

注意 1: Array.isArrayArray.prototype.includes 已经返回布尔值,因此无需对照布尔值检查它们.

Note 1: Array.isArray and Array.prototype.includes already returning booleans so there is no need to check them against booleans.

注意 2:您可以使用 NOT 运算符 (!) 翻转布尔值的值.

Note 2: You can flip the value of a boolean using the NOT operator (!).

注意 3:您必须在找到结果后立即返回(如果找到),这样您就不会浪费时间寻找已有的东西.

Note3: You have to return the result (if found) immediately after it is found so you won't waste time looking for something you already have.

注4: 搜索的返回结果将是一个对象(如果找到)并且由于对象是通过引用而不是通过值传递的,更改该对象的属性将更改原始的属性对象也是.

Note4: The return result of the search will be an object (if found) and since objects are passed by reference not by value, changing the properties of that object will change the properties of the original object too.

找到最深的物体:

如果您想找到最深的对象,则必须遍历对象 obj 中的每个对象和子对象,并且每次必须存储对象及其深度(如果结果的深度当然比之前的结果大).这是带有一些注释的代码(我使用了一个内部函数 _find,它实际上在所有对象上被调用):

If you want to find the deepest object, you'll have to go throug every object and sub-object in the object obj and everytime you have to store the object and it's depth (if the depth of the result is bigger than the previous result of course). Here is the code with some comments (I used an internal function _find that actually get called on all the objects):

function findItem (item, obj) {
    var found = null;              // the result (initialized to the default return value null)
    var depth = -1;                // the depth of the current found element (initialized to -1 so any found element could beat this one) (matched elements will not be assigned to found unless they are deeper than this depth)

    function _find(obj, d) {       // a function that take an object (obj) and on which depth it is (d)
        for (var key in obj) {     // for each ...
            // first call _find on sub-objects (pass a depth of d + 1 as we are going to a one deep bellow)
            if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) { 
                _find(obj[key], d + 1);
            }
            // then check if this object actually contain the item (we still at the depth d)
            else if (obj[key] === item || (Array.isArray(obj[key]) && obj[key].includes(item))) {
                // if we found something and the depth of this object is deeper than the previously found element
                if(d > depth) {
                    depth = d;     // then assign the new depth
                    found = obj;   // and assign the new result
                }
            }
        }
    }
    _find(obj, 0);                 // start the party by calling _find on the object obj passed to findItem with a depth of 0

    // at this point found is either the initial value (null) means nothing is found or it is an object (the deepest one)
    return found;
}

这篇关于Javascript 对象递归以在最深层查找项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆