Reputation: 3709
If I have an array of arrays, each consisting of object property names (strings), how can I recursively modify an object to check whether or not the property exists and add it accordingly. The last value in the array would be applied as a string value of the given property.
const propsToAdd = [
['propA', 'value'],
['propB', 'propC', 'propD', 'value'],
['propB', 'propF', 'value']
];
The resulting object would contain the relevant properties (nested accordingly) and the value of the final property would be equal to the last item in the array.
const resultingObj = {
propA: 'value',
propB: {
propC: {
propD: 'value'
}
propF: 'value'
}
};
I would like to create such an object recursively, as the array will be of unknown length, as will the sub arrays.
It's important to note that the following will not occur and does not need be accommodated.
const propsToAdd = [
['propA', 'value'],
['propA', 'value', 'value1']
];
Put otherwise, value
(as a child of propA
) cannot both be a property and a value name.
How can I write a recursive function that adds (and nests) key/value pairs to an object?
Upvotes: 3
Views: 4309
Reputation: 717
Alternatively,
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);
});
};
Usage;
addObjectProperties(propsToAdd);
Result;
resultingObj=
{
propA:'value1',
propB:{
propC:{
propD: 'value2'
},
propF: 'value3'
}
};
From the question:
It's important to note that the following will not occur and does not need be accommodated.
In a scenario where paths and values come separated, please use the following function instead;
function addObjectProperties(properties,value={})
{
properties.forEach(property=>
{
property.reduce(function(previous,current,idx,arr)
{
return previous[current]??=idx===arr.length-1
? value
: {};
},resultingObj);
});
};
Upvotes: 0
Reputation: 2614
A closure is here to iterate over all the property lists that are to be added to the object.
Whenever a new property is found, a new object is created. That new object is sent for further extensions.
Whenever we get to the last value of the property list, it is assigned to the current property.
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);
Upvotes: 1
Reputation: 5963
Since your use of const
suggests ES2015, you can make use of arrow functions, destructuring assignment, and default 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));
Upvotes: 6
Reputation: 1441
It's not recursive version, but why not?
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;
}
Upvotes: 0
Reputation: 2380
createRec recursively creates the object in a nested form.
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']
]));
Upvotes: 4