2017-09-13 43 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? –