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

按属性名递归搜索对象中的值

陶裕
2023-03-14

我正在构建一个实用程序函数,它应该搜索属性名称,并在找到后返回其值。它应该递归地执行此操作:

// Function
util.findVal = (object, propName) => {
  for (let key in object) {
    if (key === propName) {
      console.log(propName)
      console.log(object[key])
      return object[key]
    } else {
      util.findVal(object[key], propName)
    }
  }
}

// Input
object: {
  photo: {
    progress: 20
  }
}

// Usage
util.findVal(object, 'progress')

但是,控制台日志将永远消失,浏览器将崩溃。我做错了什么?

编辑:

这就是我调用函数的方式:

// Input

item: {
  photo: {
    file: {},
    progress: 20
  }
}

this.findProgress(item)

methods: {
  findProgress (item) {
    return util.findVal(item, this.propName)
  }
}

共有3个答案

洪涵亮
2023-03-14

如果可以避免,请不要编写自己的实用程序。

使用类似于jsonpath的东西

支持的语法的一些示例

JSONPath                   Description
$.store.book[*].author      The authors of all books in the store
$..author                   All authors
$.store.*                   All things in store, which are some books and a red bicycle
$.store..price              The price of everything in the store
$..book[2]                  The third book
$..book[(@.length-1)]       The last book via script subscript
$..book[-1:]                The last book via slice
$..book[0,1]                The first two books via subscript union
$..book[:2]             The first two books via subscript array slice
$..book[?(@.isbn)]          Filter all books with isbn number    
魏彦
2023-03-14

您的代码有一些错误:

  • 您正在递归调用util。findVal但不返回调用结果。代码应该是returnutil。findVal(…)
  • 您没有将属性名传递给递归调用
  • 您没有处理引用循环的可能性
  • 如果一个对象包含一个键以及包含该键的子对象,则返回的值是随机的(取决于分析键的顺序)

第三个问题是什么会导致无限递归,例如:

var obj1 = {}, obj2 = {};
obj1.x = obj2; obj2.y = obj1;

如果您只是在obj1obj2中递归搜索,可能会导致无限递归。

ES6增加了使用对象可用作键的 SetMap检查对象标识的可能性。这允许更快的(次线性)搜索时间。

按深度顺序运行的搜索解决方案可以是,例如:


  
   function findVal(obj, key) {
    var seen = new Set, active = [obj];
    while (active.length) {
        var new_active = [], found = [];
        for (var i=0; i<active.length; i++) {
            Object.keys(active[i]).forEach(function(k){
                var x = active[i][k];
                if (k === key) {
                    found.push(x);
                } else if (x && typeof x === "object" &&
                           !seen.has(x)) {
                    seen.add(x);
                    new_active.push(x);
                }
            });
        }
        if (found.length) return found;
        active = new_active;
    }
    return null;
}

  

给定一个对象和一个属性名,返回在找到它们的第一个深度处使用该名称找到的所有值(可以有多个值:例如,在搜索键 “z”{x:{z:1},y:{z:2}时,两个值位于同一深度)。

函数还可以正确处理自引用结构,避免无限搜索。

干宏邈
2023-03-14

您可以使用对象。键并使用数组#一些进行迭代。

function findVal(object, key) {
    var value;
    Object.keys(object).some(function(k) {
        if (k === key) {
            value = object[k];
            return true;
        }
        if (object[k] && typeof object[k] === 'object') {
            value = findVal(object[k], key);
            return value !== undefined;
        }
    });
    return value;
}

var object =  { photo: { progress: 20 }};
console.log(findVal(object, 'progress'));
 类似资料:
  • 问题内容: 我试图返回一个像这样的JSON对象结构中的特定节点 因此,这是一个树状的儿童-父母关系。每个 节点 都有唯一的ID。我试图找到一个特定 节点 这样 我通过执行搜索。但是,即使搜索找到匹配项,该函数也会始终返回。我有一种不好的感觉,即递归函数在找到匹配项后不会停止并继续运行finally返回,因为在后者的递归执行中,它没有到达返回点,但是我不确定如何解决这个问题。 请帮忙! 问题答案:

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

  • 我有一个对象的arraylistTile有我想创建一个搜索函数,在这里我迭代遍历瓷砖的每个属性和arraylist中每个颜色内的每个属性(就像每个循环的嵌套),有没有一种简单的方法可以做到这一点?

  • 问题内容: 如何通过属性区分已发布的OSGI服务,这些服务实现了相同的接口? 问题答案: 假设您要基于属性的某些值来检索注册的服务,则需要使用 过滤器 (基于LDAP语法)。 例如: 您想在其中查找实现且属性值等于的服务。 这是获取参考的相关javadoc。 备注1: 上面的示例和javadoc引用了发行版4.2。如果您不限于J2SE 1.4运行时,建议您看一下Release 4.3 语法,您可以

  • 我有嵌套父子项的: 使用: 我访问第一级项目“A”:。 现在,我迭代每个第一级“A”项来访问他们的孩子——第二级项目“B”: 在第二个层次,我不知道下面是否有任何第三个层次的项目“C”。如何确保函数向下推进,因为下面有嵌套的项目,将项目添加到列表中,直到它到达末尾?

  • 我有一个如下所示的对象;