2017-09-13 48 views
0

目的:在一个循环递归,指数计数丢失

我正在开发使用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.

任何人都知道为什么? 如果你知道有任何其他方式进行这种转换,请分享它。

亲切的问候。

+0

B:{X:{Y:1},{Z :2}}不是有效的json – marvel308

+0

@ marvel308:根本没有JSON。你说得对,'b:{x:{y:1},{z:2}},'包含一个无效的对象初始值设定项。 –

+0

yup我想'b:{x:{y:1},{z:2}}'应该是'b:{x:[{y:1},{z: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);

2

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

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

propertyvalue也应该在recur内声明;一般来说,你可以在最里面的范围声明变量。 (temp根本不需要声明,因为你永远不会使用它。)

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

+0

谢谢;应继续进行改造工作;总是认为最好从循环和/或递归中去除“var”以获得更好的性能(但是,行为可能经常变得异常)。 –

2

为了转换一个有效的对象,你可以使用迭代和递归的方法获取值及其路径。

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);

单迭代器/新结果

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));

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"; 
 
}

+1

只是一个提示,如果你有值,像'null',你把它当作对象(它是),但你需要把它当作值。你需要'if(value && isObj(value)){'。我会将声明从'for'循环移出。 –

+0

谢谢。 :D尽快实施变更。 –

+0

但isObj()中的(返回typeof值===“object”)尚未满足null?或者可以(typeof null ===“object”)返回true? –