convert array to object javascript - 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));

Related

JavaScript: Convert dot notation string to array [duplicate]

I'm trying to create a JS object dynamically providing a key and a value. The key is in dot notation, so if a string like car.model.color is provided the generated object would be:
{
car: {
model: {
color: value;
}
}
}
The problem has a trivial solution if the key provided is a simple property, but i'm struggling to make it work for composed keys.
My code:
function (key, value) {
var object = {};
var arr = key.split('.');
for(var i = 0; i < arr.length; i++) {
object = object[arr[i]] = {};
}
object[arr[arr.length-1]] = value;
return object;
}
your slightly modified code
function f(key, value) {
var result = object = {};
var arr = key.split('.');
for(var i = 0; i < arr.length-1; i++) {
object = object[arr[i]] = {};
}
object[arr[arr.length-1]] = value;
return result;
}
In the loop you should set all of the props but the last one.
Next set the final property and all set.
If you're using lodash you could use _.set(object, path, value)
const obj = {}
_.set(obj, "car.model.color", "my value")
console.log(obj)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
Use namespace pattern, like the one Addy Osmani shows: http://addyosmani.com/blog/essential-js-namespacing/
Here's the code, pasted for convenience, all credit goes to Addy:
// top-level namespace being assigned an object literal
var myApp = myApp || {};
// a convenience function for parsing string namespaces and
// automatically generating nested namespaces
function extend( ns, ns_string ) {
var parts = ns_string.split('.'),
parent = ns,
pl, i;
if (parts[0] == "myApp") {
parts = parts.slice(1);
}
pl = parts.length;
for (i = 0; i < pl; i++) {
//create a property if it doesnt exist
if (typeof parent[parts[i]] == 'undefined') {
parent[parts[i]] = {};
}
parent = parent[parts[i]];
}
return parent;
}
// sample usage:
// extend myApp with a deeply nested namespace
var mod = extend(myApp, 'myApp.modules.module2');
function strToObj(str, val) {
var i, obj = {}, strarr = str.split(".");
var x = obj;
for(i=0;i<strarr.length-1;i++) {
x = x[strarr[i]] = {};
}
x[strarr[i]] = val;
return obj;
}
usage: console.log(strToObj("car.model.color","value"));
I would use a recursive method.
var createObject = function(key, value) {
var obj = {};
var parts = key.split('.');
if(parts.length == 1) {
obj[parts[0]] = value;
} else if(parts.length > 1) {
// concat all but the first part of the key
var remainingParts = parts.slice(1,parts.length).join('.');
obj[parts[0]] = createObject(remainingParts, value);
}
return obj;
};
var simple = createObject('simple', 'value1');
var complex = createObject('more.complex.test', 'value2');
console.log(simple);
console.log(complex);
(check the console for the output)
Here's a recursive approach to the problem:
const strToObj = (parts, val) => {
if (!Array.isArray(parts)) {
parts = parts.split(".");
}
if (!parts.length) {
return val;
}
return {
[parts.shift()]: strToObj(parts, val)
};
}

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

ways to convert array to object in my case

I face this problem a lots and I tired of writing conversion function
I can do
function toObject(arr) {
var rv = {};
for (var i = 0; i < arr.length; ++i)
rv[i] = arr[i];
return rv;
}
but is there short-cut for that? my case as below :
angular.forEach($scope.data, function(item){
if(thread.checked === true){
var links = item.url;
chrome.tabs.create(links, function(tab) {
});
}
});
I'm using chrome API where links is obj :
chrome.tabs.create(obj, function(tab) {
});
In an ES5 browser you can do:
var obj = {};
[0,1,2].forEach(function(v, i){obj[i] = v});
or
[0,1,2].forEach(function(v, i, arr){this[i] = v}, obj);
As a function:
function toObj(arr) {
var obj = {};
arr.forEach(function(v, i){obj[i] = v});
return obj;
}
If the object passed in may not be an array but an object with properties 0 to n, then:
function toObj(arr) {
var obj = {};
[].forEach.call(arr, function(v, i){obj[i] = v});
return obj;
}

Javascript nested objects from string

I've got an empty object and a string:
var obj = {};
var str = "a.b.c";
Is there a way I can turn this into
obj = { a: { b: { c: { } } } }
I can't quite wrap my head around this one and I'm not even sure if it would be possible.
var obj = {};
var str = "a.b.c";
var arr = str.split('.');
var tmp = obj;
for (var i=0,n=arr.length; i<n; i++){
tmp[arr[i]]={};
tmp = tmp[arr[i]];
}
ES6:
let str = "a.b.c",
arr = str.split('.'),
obj, o = obj = {};
arr.forEach(key=>{o=o[key]={}});
console.log(obj);
ES6/Reduced (array storage unnecessary):
let str = "a.b.c", obj, o = obj = {};
str.split('.').forEach(key=>o=o[key]={});
console.log(obj);
ES6/Array.prototype.reduce:
let str = "a.b.c", last;
let obj = str.split('.').reduce((o, val) => {
if (typeof last == 'object')
last = last[val] = {};
else
last = o[val] = {};
return o;
}, {});
console.log(obj);
This is from the yui2 yahoo.js file.
YAHOO.namespace = function() {
var a=arguments, o=null, i, j, d;
for (i=0; i<a.length; i=i+1) {
d=(""+a[i]).split(".");
o=YAHOO;
// YAHOO is implied, so it is ignored if it is included
for (j=(d[0] == "YAHOO") ? 1 : 0; j<d.length; j=j+1) {
o[d[j]]=o[d[j]] || {};
o=o[d[j]];
}
}
return o;
};
See the source for documentation.
https://github.com/yui/yui2/blob/master/src/yahoo/js/YAHOO.js
This recursive function returns you the string representation of the desired object
//Usage: getObjectAsString('a.b.c'.split(/\./))
function getObjectAsString (array){
return !array.length ? '{}'
: '{"' + array[0] + '":' + getObjectAsString (array.slice(1)) + '}';
}
Now you can convert the output of getObjectAsString into object using
JSON.parse(getObjectAsString('a.b.c'.split(/\./)))
EDIT: Removed 'Input as String' version as it works only for single letter subparts in the namespace such as the one given in the question (a.b.c) which is generally not the case.
Here you go:
var string = "a.b.c",
array = string.split('.');
JSON.parse("{\"" + array.join('": {\"') + "\": {" +array.map(function () {return '}'}).join('') + "}")
Example
Here's my take on it:
function ensureKeys(str, obj) {
for(var parts = str.split('.'), i=0, l=parts.length, cache=obj; i<l; i++) {
if(!cache[parts[i]]) {
cache[parts[i]] = {};
}
cache = cache[parts[i]];
}
return obj;
}
var obj = {};
ensureKeys('a.b.c', obj);
// obj = { a: { b: { c: {} } } }

Categories

Resources