2016-07-14 96 views
2

如果我有一個數組數組,每個數組都包含對象屬性名稱(字符串),如何遞歸地修改對象以檢查屬性是否存在並相應地添加它。數組中的最後一個值將作爲給定屬性的字符串值應用。遞歸添加對象屬性

const propsToAdd = [ 
    ['propA', 'value'], 
    ['propB', 'propC', 'propD', 'value'], 
    ['propB', 'propF', 'value'] 
]; 

生成的對象將包含相關屬性(相應嵌套),最終屬性的值將等於數組中的最後一項。

const resultingObj = { 
    propA: 'value', 
    propB: { 
     propC: { 
      propD: 'value' 
     } 
     propF: 'value' 
    } 
}; 

我想遞歸創建這樣一個對象,作爲該陣列將是未知的長度,如將子陣列。

重要的是要注意,以下將不會發生並且不需要適應。

const propsToAdd = [ 
    ['propA', 'value'], 
    ['propA', 'value', 'value1'] 
]; 

把否則,value(爲propA孩子)不能同時爲一個屬性值名稱。

我該如何編寫一個遞歸函數,將鍵/值對添加(並嵌套)到對象?

+0

是有限制親的名單的深度perties? – abigwonderful

+0

不,沒有。 – Himmel

+0

數值是否在這裏?或字符串「值」@Himmel – Ayan

回答

3

createRec以嵌套形式遞歸創建對象。

function processInput(propsToAdd) { 
 
    var resultingObj = {}, 
 
    propArr; 
 

 
    for (var i = 0, len = propsToAdd.length; i < len; i += 1) { 
 
    propArr = propsToAdd[i]; 
 
    createRec(propArr, resultingObj); 
 
    } 
 

 
    return resultingObj; 
 
} 
 

 
function createRec(propArr, resultingObj, index) { 
 
    var prop, 
 
    value_Str = 'value'; 
 
    for (var j = index || 0, len1 = propArr.length; j < len1; j += 1) { 
 
    prop = propArr[j]; 
 
    if (!resultingObj[prop]) { 
 
     resultingObj[prop] = {}; 
 
    } 
 
    if (propArr[j + 1] === value_Str) { 
 
     resultingObj[prop] = propArr[j + 1]; 
 
     j += 1; 
 
    } else { 
 
     createRec(propArr, resultingObj[prop], j + 1); 
 
     j = len1; 
 
    } 
 
    } 
 
} 
 

 
console.log(processInput([ 
 
    ['propA', 'value'], 
 
    ['propB', 'propC', 'propD', 'value'], 
 
    ['propB', 'propF', 'value'] 
 
]));

+0

@Himmel請驗證並讓我知道你是否有顧慮。 – Ayan

+0

這很好,謝謝! – Himmel

0

這不是遞歸版本,但爲什麼不呢?

function createObj(propsToAdd){ 
    obj = {} 
    for(var i = 0; i < propsToAdd.length; i++){ 
     var tmp = obj; 
     var props = propsToAdd[i]; 
     for(var j = 0; j < props.length-2; j++){ 
      var prop_name = props[ j ]; 
      if(!(prop_name in tmp)) 
       tmp[ prop_name ] = {} 
      tmp = tmp[ prop_name ]; 
     } 
     if(props.length > 1) 
      tmp[ props[ j ] ] = props[ j + 1 ] 
     else 
      obj = props[0]; 
    } 
    return obj; 
} 
1

閉包在這裏迭代要添加到對象的所有屬性列表。

每當找到新屬性時,都會創建一個新對象。 該新對象被髮送進一步擴展。

每當我們到達屬性列表的最後一個值時,它就會被分配給當前屬性。

var addProperties = (function() { 
 

 
    var addProperties = function(object, properties) { 
 
    var currentProperty = properties.shift(); 
 
    if (properties.length === 1) { 
 
     object[currentProperty] = properties[0]; 
 
    } 
 
    else{ 
 
     if (!object.hasOwnProperty(currentProperty)) 
 
     object[currentProperty] = {}; 
 
     addProperties(object[currentProperty], properties); 
 
    } 
 
    }; 
 

 

 
    return function(object, propertiesArray) { 
 
    propertiesArray.forEach(function(propertyList) { 
 
     addProperties(object, propertyList); 
 
    }); 
 
    }; 
 

 
}()); 
 

 

 
const propsToAdd = [ 
 
    ['propA', 'value'], 
 
    ['propB', 'propC', 'propD', 'value'], 
 
    ['propB', 'propF', 'value'] 
 
]; 
 
var object = {}; 
 
addProperties(object, propsToAdd); 
 
console.log(object);

3

由於您的const使用建議ES2015,你可以利用arrow functionsdestructuring assignmentdefault parameters

const nest = ([x, ...xs], o={}) => 
 
    xs.length === 0 ? x : (o[x] = nest(xs,o[x]), o); 
 

 
const nestmany = ([xs, ...yss], o={}) => 
 
    xs === undefined ? o : nestmany(yss, nest(xs,o)); 
 

 
const propsToAdd = [ 
 
    ['propA', 'value1'], 
 
    ['propB', 'propC', 'propD', 'value2'], 
 
    ['propB', 'propF', 'value3'] 
 
]; 
 

 
console.log(nestmany(propsToAdd));