递归添加对象属性

Recursively add object properties

本文关键字:属性 对象 添加 递归      更新时间:2023-09-26

如果我有一个数组数组,每个数组都由对象属性名称(字符串)组成,我如何递归修改对象以检查该属性是否存在并相应地添加它。数组中的最后一个值将作为给定属性的字符串值应用。

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的子项)不能既是属性名称又是值名称。

如何编写一个递归函数来向对象添加(和嵌套)键/值对?

由于您使用 const 建议使用 ES2015,因此您可以使用箭头函数、解构赋值和默认参数:

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

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

此处使用闭包来迭代要添加到对象中的所有属性列表。

每当找到新属性时,都会创建一个新对象。该新对象将发送以进行进一步的扩展。

每当我们到达属性列表的最后一个值时,它都会分配给当前属性。

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

它不是递归版本,但为什么不呢?

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

或者,

const resultingObj={propA:'value6'};
const propsToAdd=[
    [
        'propA',
        'value1'
    ],
    [
        'propB',
        'propC',
        'propD',
        'value2'
    ],
    [
        'propB',
        'propF',
        'value3'
    ]
];
function addObjectProperties(properties)
    {
        properties.forEach(property=>
        {
            property.reduce(function(previous,current,idx,arr)
            {
                return idx===arr.length-1
                   ? previous
                   : idx===arr.length-2
                     ? previous[current]=arr[arr.length-1]
                     : previous[current]??={};
            },resultingObj);
        });
    };

用法;

addObjectProperties(propsToAdd);

结果;

resultingObj=
    {
        propA:'value1',
        propB:{
            propC:{
                propD: 'value2'
            },
            propF: 'value3'
        }
    };

从问题:

请务必注意,以下情况不会发生,也不会发生需要适应。

在路径和值分开的情况下,请改用以下函数;

function addObjectProperties(properties,value={})
    {
        properties.forEach(property=>
        {
            property.reduce(function(previous,current,idx,arr)
            {
                return previous[current]??=idx===arr.length-1
                                       ? value
                                       : {};
            },resultingObj);
        });
    };