Not sure if this can even be done, but I'll ask anyway:
Suppose if I have an array of names:
['bob', 'sue', 'dan']
And I want to dynamically create an object from those names:
bob.sue.dan = 5;
Is it possible?
Here you go, will preserve existing objects:
var namespace = function(name, separator, container){
var ns = name.split(separator || '.'),
o = container || window,
i,
len;
for(i = 0, len = ns.length; i < len; i++){
o = o[ns[i]] = o[ns[i]] || {};
}
return o;
};
e.g. usage:
namespace("com.example.namespace");
com.example.namespace.test = function(){
alert("In namespaced function.");
};
or for your example using an array.
var ns = ['bob', 'sue', 'dan'];
namespace(ns.join('.'));
bob.sue.dan.foobar = true;
or extending an existing object:
var bob = {}
namespace("foo.bar",".",bob);
bob.foo.bar = true;
Edit: updated as requested:
var namespace = function(name, separator, container, val){
var ns = name.split(separator || '.'),
o = container || window, i, len;
for(i = 0, len = ns.length; i < len; i++){
var v = (i==len-1 && val) ? val : {};
o = o[ns[i]] = o[ns[i]] || v;
}
return o;
};
namespace("bob.sue.dan",null,null,5);
alert(bob.sue.dan);
See working example: http://jsfiddle.net/herostwist/hu6j9/
Then you can do:
function makeOjectTree(propNames) {
var name;
var o = {};
var result = o;
for (var i=0, iLen=propNames.length; i<iLen; i++) {
name = propNames[i];
if (!o[name]) {
o[name] = {};
o = o[name];
}
}
return result;
}
var names = ['bob', 'sue', 'dan'];
var objs = [];
for(var i=0; i<names.length; i++) {
objs.push(names[i]);
var val = (i==names.length-1) ? "5" : "{}";
eval(objs.join(".") + " = " + val);
}
alert(bob.sue.dan);
Demo: http://jsfiddle.net/EpZm2/1/
sure you can ...
var obj = 5;
var yourarray = ['bob', 'sue', 'dan'];
yourarray = yourarray.reverse();
for(e in yourarray) {
var tmpobj = obj;
obj = new Object();
obj[yourarray[e]] = tmpobj;
// if you already have an object
if (e+1 == yourarray.length) {
your_current_existing_object[yourarray[e]] = tmpobj;
}
}
Yes this is possible.
You can define new properties on an object this way:
var obj = {};
obj["bob"] = {};
obj["bob"]["sue"] = {};
obj["bob"]["sue"]["dan"] = 5;
So you can also do it with an array of property names ;)
Related
I'm struggling with figuring out how to modify this setValue() function, so that when it encounters a numeric path segment, an array is created if it doesn't exist. I've tried assigning [] instead of {} when the path segment is numeric but it's not working as expected.
var obj = {};
setValue(obj, "Application.0.Employment.0.Id", 1);
//Not working because objects are not created as arrays
obj.Application[0].Employment.push({ Id: 2 });
function setValue(object, path, value) {
var a = path.split('.');
var o = object;
for (var i = 0; i < a.length - 1; i++) {
var n = a[i];
if (n in o) {
o = o[n];
} else {
//o[n] = isNaN(n) ? {} : [];
o[n] = {};
o = o[n];
}
}
o[a[a.length - 1]] = value;
}
You need to look ahead one index. The attempt you had in comments should be altered to:
o[n] = isNaN(a[i+1]) ? {} : [];
function setValue(object, path, value) {
var a = path.split('.');
var o = object;
for (var i = 0; i < a.length - 1; i++) {
var n = a[i];
if (n in o) {
o = o[n];
} else {
o[n] = isNaN(a[i+1]) ? {} : [];
o = o[n];
}
}
o[a[a.length - 1]] = value;
}
var obj = {};
setValue(obj, "Application.0.Employment.0.Id", 1);
console.log(JSON.stringify(obj));
obj.Application[0].Employment.push({ Id: 2 });
console.log(JSON.stringify(obj));
I have four arrays:
var attributes = ["a","b","c","d"];
var a = [1,2,3];
var b = [34,55,66];
var c = [22,23,53];
var d = [15,78,98];
How to merge them into one json like string in Nodejs?
[{"a":1,"b":34,"c":22,"d":14},
{"a":2,"b":55,"c":23,"d":78},
{"a":3,"b":66,"c":53,"d":98}]
Here is my code, but anyone have a better solution? I do need preserve the quote.
var a = [1,2,3];
var b = [34,55,66];
var c = [22,23,53];
var d = [15,78,98];
var obj = "[";
for (var u = 0; u < a.length; u++) {
var l = "\"a\":"+a[u]+",";
var m = "\"b\":"+b[u]+",";
var q = "\"b\":"+c[u]+",";
var n = "\"d\":"+d[u]+"";
if(u == (a.length-1))
var k = "{" + l + m + q + n + "}";
else
var k = "{" + l + m + q + n + "},";
console.log(k);
obj = obj + k;
};
obj = obj + "]";
console.log(obj);
Assuming all the arrays are the same length, and hardcoding their names:
var obj = []
for (var u = 0; u < a.length; u++) {
obj.push({
'a': a[u],
'b': b[u],
'c': c[u],
'd': d[u]
});
};
obj = JSON.stringify(obj);
EDIT: Converted the obj into a json string, the question had been mistakenly edited to ask for an array.
This piece of code will do the trick:
var arrays = [a, b, c, d]; // add all the arrays you want
var num = a.length; // or hardcode to the length you want
var result = [];
for(var i = 0; i < num; i++) {
var element = {};
attributes.forEach(function(attr, index) {
element[attr] = arrays[index][i];
});
result.push(element);
}
var attributes = ["a","b","c","d"];
var a = [1,2,3];
var b = [34,55,66];
var c = [22,23,53];
var d = [15,78,98];
var arrays = [a, b, c, d];
var result = [];
var num = a.length;
for(var i = 0; i < num; i++) {
var element = {};
attributes.forEach(function(attr, index) {
element[attr] = arrays[index][i];
});
result.push(element);
}
document.write(JSON.stringify(result));
var attributes = ["a","b","c","d"];
var a = [1,2,3];
var b = [34,55,66];
var c = [22,23,53];
var d = [15,78,98];
var x = [];
for (var i=0;i<3;i++) {
var obj = {};
for (var j=0;j<attributes.length;j++){
obj[attributes[j]]=eval(attributes[j]+"["+i+"]");
}
x.push(obj);
}
console.log(x);
I know there are multiple answers on this question already, but none seemed to handle the key arrays as variables who's names are introduced in the attributes array. Since I assumed that was the point of the attribute array, my solution does just that using node's global scope. It also does not assume that all the key arrays will be the same length as that is not specified (even though the example they are).
var attributes = ["a","b","c","d"];
var a = [1,2,3];
var b = [34,55,66];
var c = [22,23,53];
var d = [15,78,98];
var arr = [];
while(true){
var obj = {};
for(var i=0;i<attributes.length;i++){
if(global[attributes[i]].length)obj[attributes[i]]=global[attributes[i]].shift();
}
if(Object.keys(obj).length)
arr.push(obj);
else
break;
}
In the following fiddle, I had to emulate node's global scope by manually creating a global array, but you get the point:
Fiddle: https://jsfiddle.net/trex005/vm1yeL5d/
Important note If the arrays are not actually in the global scope, but are in some other object, you can use that object in place of global
I have the following array
['.some_class &.green_mod','.some_class &.red_mod','another_class &.green_mod','another_class &.orange_mod']
I want to get this array from it:
['.some_class &.green_mod &.red_mod','another_class &.green_mod &.orange_mod']
Is it possible?
you can try:
var preArr = ['.some_class &.green_mod', '.some_class &.red_mod', 'another_class &.green_mod', 'another_class &.orange_mod'];
var newArr = [];
preArr.forEach(function (item) {
var has = false;
var preWords = item.split('&');
for (var i = 0; i < newArr.length; ++i) {
var newWords = newArr[i].split('&');
if (newWords[0] == preWords[0]) {
has = true;
for (var j = 0; j < preWords.length; ++j) {
if (newWords.indexOf(preWords[j]) < 0) {
newWords.push(preWords[j]);
}
}
newArr[i] = newWords.join('&');
}
}
if (!has) {
newArr.push(item);
}
});
console.log(newArr);
demo
var test = (function() {
var fmap1 = function(e) { return e.trim().split(/\s+/); };
var fmap2 = function(e) { return e.join(" "); };
var fsort = function(e1,e2) { return e1[0] == e2[0] ? 0 : e1[0] > e2[0] ? 1 : -1; };
return function test(a) {
var a1 = a.map(fmap1).sort(fsort);
var s, a2 = [];
for (var i = 0, l = a1.length; i < l; i++) {
if (s != a1[i][0]) {
s = a1[i][0];
a2.push([s]);
}
a1.push.apply(a2[a2.length - 1], a1[i].slice(1));
}
return a2.map(fmap2);
};
})();
var arr = [' .some_class &.green_mod',' another_class &.green_mod','.some_class &.red_mod','another_class &.orange_mod'];
console.log(test(arr));
This seems to work for me:
var arr = ['.some_class &.green_mod','.some_class &.red_mod','another_class &.green_mod','another_class &.orange_mod'];
var obj = {};
var finalArr = [];
for(var i=0,c=arr.length;i<c;i++)
{
var parts = arr[i].split(' ');
var key = parts[0];
if(!obj[key]) obj[key] = [];
obj[key].push(parts.slice(1).join(' '));
}
var keys = Object.keys(obj);
for(var i=0,c=keys.length;i<c;i++)
{
var key = keys[i];
finalArr.push(key+' '+obj[key].join(' '))
}
console.log(finalArr);
Basically just loop through each one, and use the first word as a key to an array of strings to be appended, then loop through the object and join the keys with all of their array elements.
N.B. References to key are the first word
Solution bellow for data like key+separator+value where you are sure that there is no duplication in keys or You do not care if values are duplicated
// maping function that treats part before separator as key and saves incremetaly
// all values under that key (duplicated vales are possible)
// only one separator per input entry is allowed
function mapFun (el, obj, separator) {
var e = el.split(separator);
var key = e[0];
var val = e[1];
obj[key] = obj[key] ? obj[key] + separator + val : separator + val;
}
function combineClasses (arr) {
var result = [];
var separator = ' &';
var obj = Object.create(null); // create empty object without any properties or inheritance chain
for (var i=0; i<arr.length; i++) {
mapFun(arr[i], obj, separator);
}
for (var p in obj) {
result.push (p + obj[p]);
}
return result;
}
combineClasses(arr);
Bellow solution will work for data like before and data like key+separator+value1+separator+value2 and will not allow for duplicated values for the same key
function mapFun (el, separator, obj) {
var parts = el.split(separator);
var key = parts[0];
if (!obj[key]) {
obj[key] = Object.create(null);
}
for (var i=1; i<parts.length; i++) {
obj[key][parts[i]] = null;
}
}
function combineClasses (arr) {
var result = [];
var separator = ' &';
var obj = Object.create(null); // create empty object without any properties
for (var i=0; i<arr.length; i++) {
mapFun(arr[i], separator, obj);
}
for (var p in obj) {
var values = Object.keys(obj[p]).join(separator);
result.push (p + separator + values);
}
return result;
}
combineClasses(arr);
arr is where Your data comes in
var arr = ['.some_class &.green_mod','.some_class &.red_mod','another_class &.green_mod','another_class &.orange_mod']
This question already has answers here:
Split array of objects into new arrays based on year of object's date
(3 answers)
Closed 9 years ago.
I was wondering how I could turn this:
var data = [
{id:1,option1:'short',option2:'red',option3:'gold'},
{id:2,option1:'short',option2:'red',option3:'silver'},
{id:3,option1:'short',option2:'blue',option3:'gold'},
{id:4,option1:'short',option2:'blue',option3:'silver'},
{id:5,option1:'long',option2:'red',option3:'gold'},
{id:6,option1:'long',option2:'red',option3:'silver'},
{id:7,option1:'long',option2:'blue',option3:'gold'},
{id:8,option1:'long',option2:'blue',option3:'silver'}]
Into something formatted like this using Jquery.
var new_data = {
short:{
red:{gold:1,silver:2},
blue:{gold:3,silver:4}
},
long:{
red:{gold:5,silver:6},
blue:{gold:7,silver:8}
}
}
That is easier than you might think. Try this:
function helper(obj,tree,value) {
for( var i=0, l=tree.length; i<l-1; i++) {
obj[tree[i]] = obj[tree[i]] || {};
obj = obj[tree[i]];
}
obj[tree[i]] = value;
}
var new_data = {}, l = data.length, i;
for( i=0; i<l; i++) {
helper(new_data,[data[i].option1,data[i].option2,data[i].option3],data[i].id);
}
This plain JS will do it:
var data = […];
var new_data = {};
for (var i=0; i<data.length; i++) {
var o = new_data;
for (var j=1; j<3; j++) {
var prop = data[i]["option"+j];
o = o[prop] || (o[prop] = {});
}
o[data[i]["option"+j]] = data[i].id;
}
But it looks easier to use that nested schema in the first place?
You can use .reduce() like this:
var new_data = data.reduce(function(res, obj) {
if (!res[obj.option1])
res[obj.option1] = {};
if (!res[obj.option1][obj.option2])
res[obj.option1][obj.option2] = {};
res[obj.option1][obj.option2][obj.option3] = obj.id;
return res;
}, {});
or like this:
var new_data = data.reduce(function(res, obj) {
var o = res;
for (var i = 1; i < 3; i++)
o = (o[obj["option" + i]] = o[obj["option" + i]] || {});
o[obj.option3] = obj.id;
return res;
}, {});
obj = {'a':['hello', 'hie'], 'b':['World', 'India']}
To
array = [{'a':'hello','b':'World'}, {'a':'hie','b':'India'}]
Best way to convert this or any build-in method for this conversion using JQuery.
Try this Code,
obj = {'a':['hello', 'hie'], 'b':['World', 'India']}
var key = Object.keys(obj);
array = [];
for (var i = 0; i < obj['a'].length; i++){
o = {}
for (k in key){
o[key[k]] = obj[key[k]][i]
}
array.push(o)
}
var obj = {'a':['hello', 'hie'], 'b':['World', 'India']};
var array = [];
for (var prop in obj)
for (var i=0; i<obj[prop].length; i++) {
var o = array[i] || (array[i] = {});
o[prop] = obj[prop][i];
}
No jQuery needed. With jQuery, it might look like this:
var array = [];
$.each(obj, function(prop) {
$.each(this, function(i) {
var o = array[i] || (array[i] = {});
o[prop] = this;
});
});
slower and less readable. Do not use.