Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 遍历对象获取密钥和所有父密钥_Javascript_Json_Recursion_Tree_Traversal - Fatal编程技术网

Javascript 遍历对象获取密钥和所有父密钥

Javascript 遍历对象获取密钥和所有父密钥,javascript,json,recursion,tree,traversal,Javascript,Json,Recursion,Tree,Traversal,遍历树(json),使用JS实现getKeys(data,str)函数。获取密钥和所有父密钥 const data = { key1: 'str1', key2: { key3: 'str3', key4: 'str4', key5: { key6: 'str6', key7: 'str7', key8: 'str8', }, } } 例如: data = { a: 1, b: {

遍历树(json),使用JS实现getKeys(data,str)函数。获取密钥和所有父密钥

const data = {
  key1: 'str1',
  key2: {
    key3: 'str3',
    key4: 'str4',
    key5: {
      key6: 'str6',
      key7: 'str7',
      key8: 'str8',
    },
  }
}
例如:

data = {
    a: 1,
    b: {
        c: 2
    },
    d: {
        e: {
            e1: 3,
            e2: 33,
        },
        f: {
            f1: 4,
            f2: 44,
        },
    }
};
获取密钥(数据“str1”); return:'key1'

获取密钥(数据“str3”); return:'key2,key3'

获取密钥(数据“str6”); return:'key2,key5,key6'

我认为它可以通过递归实现,但是如何实现呢

这是我的解决方案,但失败了

let s = [];
function getKeys(data, str, key='') {
  if (key !== '') {
    s.push(key);
  }
  for (item in data) {
    if (typeof data[item] === 'object') {
      getKeys(data[item], str, item);
    } else if (data[item] === str) {
      s.push(item);
      return s;
    }
  }
  return s;
}

代码的问题在于,它无条件地填充“found”列表,不管该值是否在当前处理的分支下。例如,考虑:

data = {
    a: 1,
    b: {
        c: 2
    },
    d: {
        e: {
            e1: 3,
            e2: 33,
        },
        f: {
            f1: 4,
            f2: 44,
        },
    }
};
执行
getKeys(data,44)
时,返回值将是
['b','d','e','f','f2']
,这是不正确的

您需要做的是检查值是否实际位于当前节点下,并且仅当答案为“是”时才添加当前键。例如:

function getKeys(obj, val) {
    if (!obj || typeof obj !== 'object')
        return;

    for (let [k, v] of Object.entries(obj)) {
        if (v === val)
            return [k];
        let path = getKeys(v, val);
        if (path)
            return [k, ...path];

    }
}

假设您只搜索
string
键,我们可以使用递归和回溯来检查键的子对象是否具有指定的值

如果有,则在最终搜索字符串中添加父键

为此,我使用
Object.entries()
检查了每个
[键,值]
对,并使用
Array.prototype.reduce()
累积结果:

var数据={
键1:‘str1’,
关键2:{
键3:‘str3’,
键4:‘str4’,
关键5:{
键6:‘str6’,
键7:‘str7’,
键8:‘str8’,
},
}
}
功能获取键(数据、键、acc){
返回Object.entries(数据).reduce((acc、ele、idx)=>{
if(元素包括(键)和元素类型[1]=“字符串”){
acc.push(ele[0]);
}
if(元素[1]的类型=“对象”&&&!Array.isArray(元素[1])&&!(元素[1]实例的日期)){
let old=根据切片();
获取密钥(ele[1],密钥,acc);
如果(旧长度!==附件长度){
acc.unshift(ele[0]);
}
}  
返回acc;
},acc)。加入(“”);
}
log(getkey(数据,'str1',[]);
log(getkey(数据,'str3',[]);

log(getkey(数据,'str6',[])我将投票重新打开,但是:请再次编辑,并描述您尝试的代码以何种方式失败。这将帮助人们更好地理解如何回答……谢谢你,乔治!你明白我为什么失败了。简单地解决它。从你身上学到了很多。谢谢@子龙盘:随时;)