【问题标题】:Returning array of nested keys recursively javascript递归返回嵌套键数组javascript
【发布时间】:2018-08-16 19:31:41
【问题描述】:

试图创建一个返回对象键数组的函数,包括嵌套在其中的对象。我的代码如下所示:

function keyCount(obj, arr) {
  if (arr == undefined){
    arr = []
  }
  let keys = Object.keys(obj);
  let length = keys.length;
  for (i = 0; i <= length; i++){
    if (Object.keys(obj)[i] !== undefined){
      arr.push(Object.keys(obj)[i]);
    }
  }
  for (i = 0; i <= length; i++){
    if (typeof(obj[Object.keys(obj)[i]]) === "object" && obj[Object.keys(obj)[i]] !== null && Object.keys(obj)[i] !== undefined){
      let nestedobj = obj[Object.keys(obj)[i]];
      keyCount(nestedobj,arr)
    }
  }
  return (arr);
}

这将返回第一级键和一个嵌套对象的键,但在第一次递归调用后退出函数。有没有办法解决这个问题或更好的方法来格式化代码?提前致谢!

编辑: 数据预期:

let obj1 = {
1:"a",
2:{
  3: "b",
  4: "c"},
5:{
  6:"d",
  7: "e",
  8: {
    9: "f",
    10: "g"},
    11:{
      12:"h",
      13: "i"
      }
    }
  };

应该返回:

[1,2,5,3,4,6,7,8,9,10,11,12,13]

但只返回:

[1,2,5,3,4]

【问题讨论】:

  • @Durga 在这里他只要求钥匙,该问题在问题主题中具有其他含义。
  • 请添加一些数据和想要的结果。
  • 检查@Durga提到的链接
  • 你真的不应该重复调用Object.keys(obj)。这就是您创建 let keys 变量的目的!

标签: javascript object recursion nested


【解决方案1】:

您可以获取键并检查值是否为对象,然后也获取此键。

function getKeys(object) {
    return Object
        .keys(object)
        .reduce((r, k) => r.concat(k, object[k] && typeof object[k] === 'object' ? getKeys(object[k]) : []), []);
}


var object = { 1: "a", 2: { 3: "b", 4: "c" }, 5: { 6: "d", 7: "e", 8: { 9: "f", 10: "g" }, 11: { 12: "h", 13: "i" } } };

console.log(getKeys(object));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • @georg,没错,它被之前的检查object[k]保护了。
【解决方案2】:

您的代码存在各种问题。最重要的是i is implicitly global,它会导致您的递归调用改变循环条件。你很幸运,你没有陷入无限循环……

function keyCount(obj, arr) {
  "use strict";
//^^^^^^^^^^^^^ prevent mistakes with forgotten declarations
  if (arr == undefined){
    arr = []
  }
  const keys = Object.keys(obj);
//^^^^^ prefer const over let when you don't assign
  const length = keys.length;
  for (let i = 0; i < length; i++) {
//                 ^^^ don't use <=
//     ^^^ i needs to be a local variable!
    // if (keys[i] !== undefined)
//  ^^^ no longer necessary when having fixed the loop
      arr.push(keys[i]);
//             ^^^^ don't call Object.keys again
  }
  for (let i = 0; i < length; i++) {
//     ^^^          ^ same as above
    const nestedobj = obj[keys[i]]; // move this up here
//                        ^^^^ same as above
    if (typeof nestedobj === "object" && nestedobj !== null  ) {
//            ^         ^ typeof is not a function          ^ same as above
      keyCount(nestedobj, arr);
    }
  }
  return arr;
}

【讨论】:

  • 谢谢你,这非常有帮助!
【解决方案3】:

let obj1 = {
1:"a",
2:{
  3: "b",
  4: "c"},
5:{
  6:"d",
  7: "e",
  8: {
    9: "f",
    10: "g"},
    11:{
      12:"h",
      13: "i"
      }
    }
  };

var keyArray = [];

function getKeys(obj){
  // get the keys from the current level
  var keys = Object.keys( obj );
  // iterate through each key, add it to our keyArray[]
  for( var i=0, x=keys.length; i<x; i++ ){
    keyArray.push( keys[i] );
    // if there is another array/object (instead of a
    // value) send that section of the obj back into
    // the function
    if( obj[keys[i]].constructor === Object ){
      getKeys( obj[keys[i]] );
    }
  }
}

getKeys(obj1);

//Should return:
//console.log( 'expected', [1,2,5,3,4,6,7,8,9,10,11,12,13] );
console.log( 'result: ', keyArray.join(',') );

【讨论】:

  • @Leafyshark 如果我理解您的评论:从 Object.keys(obj1) 开始,然后循环遍历这些结果只会使代码下降两个级别(顶层和下一个扫描)。使用递归循环,代码可以挖掘到对象具有嵌套数据的深度。
【解决方案4】:

由于到目前为止发布的答案不处理圆形对象,所以这里有一个:

function getKeys(obj) {
    let seen = new WeakSet(),
        keys = new Set(),
        queue = [obj];

    while (queue.length) {
        let obj = queue.shift();
        
        if (!obj || typeof obj !== 'object' || seen.has(obj))
            continue;
        
        seen.add(obj);
        
        for (let [k, v] of Object.entries(obj)) {
            keys.add(k);
            queue.push(v);
        }
    }

    return [...keys];
}

//

weirdo = {a: 1, b: 2, c: 3}
weirdo.self = weirdo;
console.log(getKeys(weirdo))

而且它不是递归的,所以它可以处理超过 10,000 层的嵌套(这在当今的 webdev 中是很常见的情况;)

【讨论】:

    猜你喜欢
    • 2020-01-26
    • 2020-07-15
    • 2016-02-19
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    • 2021-01-23
    • 2019-04-25
    • 2022-01-11
    相关资源
    最近更新 更多