Dynamic object creation from an array - javascript

I want to generate a dynamic object and assign value into it. Following is the code
var chunk = "INTERNATIONALISATION#LANGUAGE#DICTIONARY#EN";
var c = chunk.split('#');
var a = {};
So the output should be like this
a["INTERNATIONALISATION"]["LANGUAGE"]["DICTIONARY"]["EN"] = 10;
Tried looping through array but nothing works for now.Please advise.

Try this:
var chunk = "INTERNATIONALISATION#LANGUAGE#DICTIONARY#EN";
var c = chunk.split('#');
var a = {};
var lastKey = c.pop();
c.reduce((obj, key) => obj[key] = obj[key] || {}, a)[lastKey] = 10;
To make it more convenient you can put it in a function:
const dynamicAssign = (object, stringPath, value) => {
const path = stringPath.split('#');
const lastKey = path.pop();
const target = path.reduce((obj, key) => obj[key] = obj[key] || {}, object);
target[lastKey] = value;
};
const a = {};
dynamicAssign(a, "INTERNATIONALISATION#LANGUAGE#DICTIONARY#EN", 10);

Related

Merging objects

I am trying to merge the objects recursively.
what I have
arrayOfObjects = [{a1:{aa:k1}},{a1:{ab:k2}},{a1:{ac:k3}},{a1:{aa:k4}},{a1:{ab:k5}}];
what I need is
{a1:{aa:k1,ab:k2,ac:k3,aa:k4,ab:k5}}
I made a function
function merg(array){
value = {};
if(array.length>0){
$.each(array, function (i) {
value = $.extend(true,{},value,array[i]);
});
}
return value;
};
console.log(merg(arrayOfObjects));
what I get is
{a1:{aa:k1,ab:k2,ac:k3}}
aa:k4,ab:k5 are missing(may due to same key value )
if the deep merge is false I get only one value
value = $.extend({},value,array[i]);
{a1:{aa:k1}}
We can make use of Symbols,
var arr = [{a1:{aa:'k1'}},{a1:{ab:'k2'}},{a1:{ac:'k3'}},{a1:{aa:'k4'}},{a1:{ab:'k5'}}];;
var op = {};
var result = {};
var globalKey;
arr.forEach((ar) => {
var [key, value] = Object.entries(ar)[0];
globalKey = key;
var [innerKey, innerValue] = Object.entries(value)[0];
op[Symbol(innerKey)] = innerValue;
});
result[globalKey] = op;
console.log(result);

creating a object from array of strings

My input is like
var resources = ["user-john","user-doe", "students-Milan"];
I am trying to get an output as an object like below,
{
user: ["john", "doe"],
students: ["Milan"]
}
What am i doing wrong
var resources = ["user-john","user-doe", "students-Milan"];
let tempObj = {}
resources.forEach(o => {
let tempArr = o.split("-");
if(tempObj[tempArr[0]]){
tempObj[tempArr[0]] = [...tempArr[1], tempArr[1]]
}else{
tempObj[tempArr[0]] = [tempArr[1]]
}
})
console.log(tempObj)
You could deconstructure the splitted string and build an array as value.
var resources = ["user-john", "user-doe", "students-Milan"],
result = resources.reduce(
(r, s) =>
((key, value) => Object.assign(r, { [key]: [].concat(r[key] || [], value) }))
(...s.split('-')),
{}
);
console.log(result);
You could use reduce method here with an object as a accumulator value.
var data = ["user-john", "user-doe", "students-Milan"];
var result = data.reduce((r, e) => {
let [key, value] = e.split('-');
r[key] = (r[key] || []).concat(value)
return r;
}, {})
console.log(result)
A clean, modern solution:
var resources = ["user-john","user-doe", "students-Milan"];
const output = {}
resources.forEach(item => {
const [key, value] = item.split('-')
output[key] = [...output[key] || [], value]
})
console.log(output)
Here in this part you actually need to :
resources.forEach(o => {
let tempArr = o.split("-");
if(tempObj[tempArr[0]]){
tempObj[tempArr[0]] = [...tempObj[tempArr[0]], tempArr[1]];
}else{
tempObj[tempArr[0]] = [tempArr[1]]
}
})
var resources = ["user-john","user-doe", "students-Milan"];
var tmp = {};
resources.forEach(function(e){
var a = e.split("-");
if(typeof tmp[a[0]] == "undefined"){
tmp[a[0]] = [];
tmp[a[0]].push(a[1]);
}else{
tmp[a[0]].push(a[1]);
}
});
console.log(tmp);
You can use .push method instead [...tempArr[1], tempArr[1]]
var resources = ["user-john","user-doe", "students-Milan"];
let tempObj = {}
resources.forEach(o => {
let tempArr = o.split("-");
if(tempObj[tempArr[0]]){
tempObj[tempArr[0]].push(tempArr[1])
}else{
tempObj[tempArr[0]] = [tempArr[1]]
}
})
console.log(tempObj)
Or you can use the spread syntax on the last state of your array like [...tempObj[tempArr[0]], tempArr[1]] instead [...tempArr[1], tempArr[1]]

How to use string as a key to update object

I am trying to create a function that accepts the path in an object and makes that the key.
for example, if I wanted to update the city, which is is a child object of a company, which is a child object of a property I could do something like this:
originalObj['property']['company']['city'] = test
Here is my code so far:
function updateObj(path, value){
let valuePath = path.split(',')
let key=''
for(let i=0; i<valuePath.length ; i++){
key = key+`[valuePath[${i}]]`
}
//key = [valuePath[0]] [valuePath[1]] [valuePath[2]]
originalObj[key] = value
}
setObj('property,company,city', test)
You could save the last key of the path and use a temporary object for getting the final object for assigning the value.
function updateObj(path, value) {
var valuePath = path.split(','),
last = valuePath.pop(),
temp = object;
for (let i = 0; i < valuePath.length; i++) {
temp = temp[valuePath[i]];
}
temp[last] = value;
}
var object = { property: { company: { city: 'London' } } };
updateObj('property,company,city', 'New York');
console.log(object);
With Array#reduce
function updateObj(path, value) {
var valuePath = path.split(','),
last = valuePath.pop();
valuePath.reduce((o, k) => o[k] = o[k] || {}, object)[last] = value;
}
var object = {};
updateObj('property,company,city', 'New York');
console.log(object);
function updateObj(obj, path, value){
path.split(",").slice(0,-1).reduce((obj, key) => obj[key] || (obj[key] = {}), obj)[path.split(",").pop()] = value;
}
Try this:
function setObj(originalObj, path, value){
var parts = path.split(',');
var lastKey = parts.pop();
var obj = originalObj;
parts.forEach(
function(key) {
key = key.trim();
obj[key] = obj[key] || {};
obj = obj[key];
}
);
obj[lastKey] = value;
}
var originalObj = {};
var test = "This is a test";
setObj(originalObj, 'property,company,city', test)
console.log(JSON.stringify(originalObj,0,2));
It walks through your list and creates sub objects for all but the last. It then uses the last as the key to store the value.
The advantage to this code is that you don't assume the original Object variable name. And, if you wanted it to be pure and not to affect the original object structure then you could make these minor changes:
function setObj(originalObj, path, value){
var parts = path.split(',');
var lastKey = parts.pop();
var newObj = Object.assign({}, originalObj);
var obj = newObj;
parts.forEach(
function(key) {
obj[key] = Object.assign({}, obj[key] || {});
obj = obj[key];
}
);
obj[lastKey] = value;
return newObj;
}
var originalObj = {animals: {dog:"bark",cat:"meow"},property:{company:{name:"Fred's Things"}}};
var test = "This is a test";
var result = setObj(originalObj, 'property,company,city', test)
console.log(JSON.stringify(originalObj,0,2));
console.log(JSON.stringify(result,0,2));

Create nested object dynamically with forEach

I have an 'path' string: 'profile.name.en';
I want to use this to create an object dynamically. I'm using this function and its working:
function set(obj, path, value) {
var schema = obj; // a moving reference to internal objects within obj
var arr = path.split('.');
var len = arr.length;
for(var i = 0; i < len-1; i++) {
var elem = arr[i];
if( !schema[elem] ) schema[elem] = {};
schema = schema[elem];
}
schema[arr[len-1]] = value;
return schema;
}
Use it like this:
var a = {};
var path = 'profile.name.en';
var profileName = 'OleFrank';
var o = set(a, path, profileName);
// result
{
profile: {
name: {
en: 'OleFrank'
}
}
}
I tried to refactor to using forEach instead of for-loop, but then it's not working anymore. Why is this??
You could use Array#reduce, because this returns the object you need, without keeping a reference outside.
function set(object, path, value) {
var keys = path.split('.'),
last = keys.pop();
keys.reduce(function (o, k) {
return o[k] = o[k] || {};
}, object)[last] = value;
}
var a = {},
path = 'profile.name.en',
profileName = 'OleFrank';
set(a, path, profileName); // no need of an assignment, because of
// call by reference with an object
console.log(a);
Version with Array#forEach
function set(object, path, value) {
var keys = path.split('.'),
last = keys.pop();
keys.forEach(function (k) {
object[k] = object[k] || {};
object = object[k];
});
object[last] = value;
}
var a = {},
path = 'profile.name.en',
profileName = 'OleFrank';
set(a, path, profileName);
console.log(a);

convert array to object javascript

I have the following array:
["recordList", "userList", "lastChanged"]
And I want something like this:
lastChangedValue = "231231443234";
var object = {};
object = {
recordList: {
userList: {
lastChanged: lastChangedValue
}
}
}
How I can do this?
Thanks in advance.
Try this:
var array = ["recordList", "userList", "lastChanged"];
var value = "231231443234";
function arrayToObject(array, object, value) {
var ref = object;
for (var i=0; i<array.length-1; ++i) {
if (!ref[array[i]]) {
ref[array[i]] = {};
}
ref = ref[array[i]]
}
ref[array[array.length-1]] = value;
return object;
}
alert(JSON.stringify(arrayToObject(array, {}, value)));
You can iterate through property names and create one nested level of new object in each iteration:
var props = ["recordList", "userList", "lastChanged"];
var lastChangedValue = "231231443234";
var obj = {}
var nested = obj;
props.forEach(function(o, i) {
nested[o] = i === props.length - 1 ? lastChangedValue : {};
nested = nested[o];
});
console.log(obj);
There are probably a bunch of ways to do it, one way is with reduce
var keys = ["recordList", "userList", "lastChanged"];
var temp = keys.slice().reverse(),
lastChangedValue = "231231443234";
var result = temp.reduce( function (obj, val, ind, arr) {
if (ind===0) {
obj[val] = lastChangedValue;
return obj;
} else {
var x = {};
x[val] = obj;
return x;
}
}, {});
console.log(result);
Solving with recursion
var fields = ["recordList", "userList", "lastChanged"];
lastChangedValue = "231231443234";
var object = {};
(function addFields(o, i, v) {
if (i == fields.length - 1) {
o[fields[i]] = v;
return;
}
o[fields[i]] = {};
addFields(o[fields[i]], ++i, v)
})(object, 0, lastChangedValue);
alert(JSON.stringify(object));

Categories

Resources