在循环递归期间,索引计数丢失

时间:2017-09-13 07:45:39

标签: javascript angularjs recursion lodash

目的:

我正在使用AngularJS和Lodash开发应用程序。我需要一个执行以下转换的函数:

{
 a: 0,
 b: {x: {y: 1, z: 2}},
 c: 3
}

{
 a: 0,
 'b.x.y': 1,
 'b.x.z': 2,
 c: 3
}

现在,我正在使用递归函数遍历对象。目前,我的代码看起来像那样(不完整):

            var obj = {},
                keys, property, value;

            var recur = function (mat) {

                keys = Object.keys(mat);

                for (var i = 0; i < keys.length; i++) {
                    property = keys[i];
                    value = mat[property];

                    if (isObj(value)) {
                        //debugger;
                        recur(value);


                    } else {
                        obj[property] = value;
                    }
                }
            }
            recur({
             a: 0,
             b: {x: {y: 1, z: 2}},
             c: 3
            });
            
            console.log(obj);
            
            function isObj(value) {
            return typeof value === "object";
        }

我在调试时遇到的一个问题是:

没有增加;在最高级别的递归调用期间,我仍为0。

任何人都知道为什么? 如果您知道进行此转换的任何其他方式,请分享。

亲切的问候。

4 个答案:

答案 0 :(得分:2)

这是因为keys声明的范围错误。它应该在内部 recur中声明。因为它不是,当recur递归时,keys会被覆盖。

这不会使i没有增加,但它确实意味着你的循环会在令人惊讶的时候终止,因为当你递归时keys会发生变化。

propertyvalue也应在recur内宣布;通常,您可以在最里面的范围内声明变量。 (temp根本不需要声明,因为你从不使用它。)

为了得到你的最终结果,显然你不得不改变,但你说代码是不完整的。这是循环无法正常工作的问题。

答案 1 :(得分:2)

为了转换有效对象,您可以使用迭代和递归方法来获取值及其值。

&#13;
&#13;
function convert(object) {
    function iter(o, p) {
        Object.keys(o).forEach(function (k) {
            var q = p.concat(k);
            if (o[k] && typeof o[k] === 'object') {
                iter(o[k], q);
                return;
            }
            object[q.join('.')] = o[k];
        });
    }

    Object.keys(object).forEach(function (k) {
        if (object[k] && typeof object[k] === 'object') {
            iter(object[k], [k]);
            delete object[k];
        }
    });
}

var object = { a: 0, b: { x: { y: 1, z: 2 } }, c: 3 };

convert(object);

console.log(object);
&#13;
&#13;
&#13;

单个迭代器/新结果

&#13;
&#13;
function convert(object) {
    function iter(o, p) {
        p = p ? p + '.' : '';
        Object.keys(o).forEach(function (k) {
            if (o[k] && typeof o[k] === 'object') {
                iter(o[k], p + k);
                return;
            }
            result[p + k] = o[k];
        });
    }

    var result = {};
    iter(object);
    return result;
}

var object = { a: 0, b: { x: { y: 1, z: 2 } }, c: 3 };

console.log(convert(object));
&#13;
&#13;
&#13;

答案 2 :(得分:1)

你可以通过以下方式完成

let obj = {
 a: 0,
 b: {x: {y: 1, z: 2}},
 c: 3
}

let result = {};
function rec(obj, parent){
   
   if(typeof obj == 'object'){
      for(let property in obj){
      
          rec(obj[property], (parent == '' ? parent:parent+'.')+property);
      }
   }
   else {
      result[parent] = obj;
   }
}

rec(obj, '');
console.log(result);

答案 3 :(得分:0)

感谢大家的帮助(尤其是@ T.J.Crowder指出我与范围有关的错误)。

我的完整代码(任何建议 - 与好/坏做法等有关 - 都欢迎):

var recur = function (obj, mat, parent) {

             var keys = Object.keys(mat);

             for (var i = 0; i < keys.length; i++) {
                    var property = keys[i];
                    var value = mat[property];

                    if (isObj(value)) {
                        recur(obj, value, parent ? parent + "." + property : property);

                    } else {
                        obj[parent ? parent + "." + property : property] = value;
                    } 
            }
            return obj;
}
            console.log(recur({}, {
             a: 0,
             b: {x: {y: 1, z: 2}},
             c: 3
            }));
            
            function isObj(value) {
            return typeof value === "object";
}