Given the following string with key-value pairs, how would you write a generic function to map it to an object?
At the moment, I am just splitting by : and ; to get the relevant data, but it doesn't seem like a clean approach.
This my code at the moment:
var pd = `id:S76519;sku:S76519;name:StarGazer 3000;model:ICC74`;
var tempPd = pd.split(';');
for (i = 1; i < tempPd.length; i++) {
var b = tempPd[i].split(':');
console.log(b[1]);
}
What about using reduce:
function objectify(str) {
return str.split(";").reduce(function (obj, item) {
var a = item.split(":");
obj[a[0]] = a[1];
return obj;
}, {});
}
var strObj = "id:S76519;sku:S76519;name:StarGazer 3000;model:ICC74";
console.log(objectify(strObj));
or:
function objectify(str){
return str.split(";").reduce((obj,item)=>{
var a = item.split(":");
obj[a[0]]=a[1];
return obj;
},{});
}
var strObj = "id:S76519;sku:S76519;name:StarGazer 3000;model:ICC74";
console.log(objectify(strObj));
Related
I implemented an aggregation function but the only problem I have now is that I lost my key: value format e.g [{name:"Apples",val:8},{name:"Banana",val: 9}].
function agrregate(a){
var targetObj = {};
var result;
var b = JSON.parse(JSON.stringify(a));
var trees= b.length;
if(!trees){
trees = 0
}
for (var i = 0; i < trees; i++) {
if (!targetObj.hasOwnProperty(b[i].key)) {
targetObj[b[i].key] = 0;
}
targetObj[b[i].key] += b[i].val;
}
result = JSON.stringify(targetObj);
return result;
}
This is the result i get when agrregate function completes.
{"Apple":8,"Banana":9}
Instead of
{name:"Apple", val:8}, {name:"Banana", val:9}
Use a reducer to aggregate. You don't need to do stuff with JSON stringify/parse.
To get back to an array of objects, you use map and Object.keys
var test = [{name:"Apples",val:5},{name:"Banana",val: 9},{name:"Apples",val:3}]
var aggregate = function(arr) {
return arr.reduce(function(result, obj) { // Create one object (result)
result[obj.name] = (result[obj.name] || 0) + obj.val; // Add a new key/or increase
return result // Return the object
}, {});
};
var wrap = function(obj) {
return Object.keys(obj) // Create an array of keys
.map(function(key) {
return { // Specify the format
name: key,
val: obj[key]
};
});
};
console.log(aggregate(test));
console.log(wrap(aggregate(test)));
I'm starting with unit testing. I need to create some fake data to run the tests. So let's say inside a stubbed method I'm passing an obj as an argument and I do things with obj.obj1.obj2.data inside the function. Is there a way to set this fake object? So, given:
obj.obj1.obj2.data
It creates:
obj = {
obj1: {
obj2: {
data: 'whatever'}}}
So it would be at the end something like:
var obj = creator('obj.obj1.obj2.data', 20);
Assuming the string is only a set of objects (no arrays) this should be fairly straightforward. Just split the input string on . and then use a while loop to do the nesting.
function creator(str,val){
var tree = str.split('.');
var ret = {};
var cur = ret;
while(tree.length){
var name = tree.shift();
cur[name] = tree.length ? {} : val;
cur = cur[name];
}
return ret;
}
document.querySelector("#out").innerHTML = JSON.stringify(creator('obj.obj1.obj2.data',20));
<div id="out"></div>
Just in case anyone else in interested, I created a simple npm module with the function below (https://github.com/r01010010/zappy) check it out:
var objFrom = function(str, last_value){
var objs = str.split('.');
var r = {};
var last = r;
for(i=0; i < objs.length; i++) {
if(i !== objs.length - 1){
last = last[objs[i]] = {};
}else{
last[objs[i]] = last_value;
}
}
return r;
}
var obj = objFrom('obj1.obj2.data', 20);
console.log(obj.obj1.obj2.data);
I have 2 objects that I need to merge and keep all properties in tact, tried with jQuery $.extend but I cant get it to work . I tried all posts with how to merge javascript objects but simply cant get this to work.
var thz_icon_source = {"Spinners":["spinnericon1","spinnericon2"],"Awesome":["awesomeicon1","awesomeicon2"]};
var fa_icon_source = {"Spinners":["faspinner1","faspinner2"],"Awesome":["faawesome1","faawesome2"]};
var new_source ={};
$.extend(new_source,fa_icon_source,thz_icon_source);
console.log(thz_icon_source);
console.log(fa_icon_source);
console.log(new_source);
desired output should be like
{
"Spinners":["faspinner1","faspinner2","spinnericon1","spinnericon2"],
"Awesome":["faawesome1","faawesome2","awesomeicon1","awesomeicon2"]
}
This post Merge two json/javascript arrays in to one array has a simple object mine is not same as that one.
Demo
function mergeJSON(json1,json2)
{
var result = json1 ;
for (var prop in json2)
{
if (json2.hasOwnProperty(prop))
{
result[prop] = result[prop].concat(json2[prop]);
}
}
return result;
}
$.extend merges in missing properties, it doesn't combine the properties that are in common. You need to write a loop.
var thz_icon_source = {
"Spinners": ["spinnericon1", "spinnericon2"],
"Awesome": ["awesomeicon1", "awesomeicon2"]
};
var fa_icon_source = {
"Spinners": ["faspinner1", "faspinner2"],
"Awesome": ["faawesome1", "faawesome2"]
};
var new_source = {};
// First add in the new elements from thz_icon_source
$.extend(new_source, fa_icon_source, thz_icon_source);
// Now merge the common elements
$.each(fa_icon_source, function(k, e) {
if (thz_icon_source.hasOwnProperty(k)) {
new_source[k] = e.concat(thz_icon_source[k]);
}
});
console.log(thz_icon_source);
console.log(fa_icon_source);
console.log(new_source);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You can use this prototype to merge 2 or more objects the way you want it:
Object.prototype.assignDeep = function() {
var self = this;
Object.keys(arguments).forEach(obj => {
Object.keys(self).forEach(val => {
if (arguments[obj].hasOwnProperty(val)) {
var tmp = arguments[obj][val] instanceof Array ? arguments[obj][val] : [arguments[obj][val]];
self[val] = self[val].concat(tmp);
}
});
});
return self;
}
var thz_icon_source = {"Spinners":["spinnericon1","spinnericon2"],"Awesome":["awesomeicon1","awesomeicon2"]};
var fa_icon_source = {"Spinners":["faspinner1","faspinner2"],"Awesome":["faawesome1","faawesome2"]};
var b = thz_icon_source.assignDeep(fa_icon_source);
console.log(b);
You should use a loops with .concat():
function objectConcatArrays(){
var a = arguments, o = {};
for(var i=0,l=a.length; i<l; i++){
for(var p in a[i]){
if(p in o){
o[p] = o[p].concat(a[i][p]);
}
else{
o[p] = a[i][p];
}
}
}
return o;
}
var thz_icon_source = {"Spinners":["spinnericon1","spinnericon2"],"Awesome":["awesomeicon1","awesomeicon2"]};
var fa_icon_source = {"Spinners":["faspinner1","faspinner2"],"Awesome":["faawesome1","faawesome2"]};
var res = objectConcatArrays(thz_icon_source, fa_icon_source);
console.log(res);
Each argument represents an Object of Arrays. Add more if you want.
I want to create a function in Javascript which takes an array as argument and returns a list of objects. I have an array like this:
var arr= [10,20,30];
console.log(listFunction(arr));
The result should look like this:
{'val':10, 'restList':{'val':20, 'restList':{'val':30,'restList':'null'}}}
I have tried the forEach() function:
function listFunction(parentArr) {
var listOfObjects = [];
parentArr.forEach(function (entry, thisArg) {
var singleObj = {}
singleObj['val'] = entry;
singleObj['restList'] = singleObj;
listOfObjects[thisArg] = singleObj;
});
return listOfObjects;
};
You need to use a recursive function:
function listFunction(arr){
if(arr.length == 0){
return null;
}else{
return {val: arr[0], restList: listFunction(arr.slice(1,arr.length))};
}
}
This is the Lisp-style recursive list algorithm.
var recursiveList = function (array) {
return recursiveListHelper(arr, {});
};
var recursiveListHelper = function (array, obj) {
if (array.length === 0) //stopping condition
return null;
var car = array[0]; //current element
var cdr = array.slice(1); //rest of list
obj = {val: car};
obj.restList = recursiveListHelper(cdr, obj);
return obj;
};
You mentioned that you wanted to avoid using Array.slice. This solution uses array indexing instead of splitting into subarrays.
var recursiveIndexed = function (array) {
return recursiveIndexedHelper(array, {}, 0);
};
var recursiveIndexedHelper = function (array, obj, index) {
if (index == array.length)
return null;
var car = array[index];
obj = {val: car };
obj.restList = recursiveIndexedHelper(array, obj, index + 1);
return obj;
};
A plunker as example.
I have this array:
["userconfig", "general", "name"]
and I would like it to look like this
data_structure["userconfig"]["general"]["name"]
I have tried this function:
inputID = "userconfig-general-name"
function GetDataByID(inputID){
var position = '';
for (var i = 0; i < inputID.length; i++) {
var hirarchy = inputID[i].split('-');
for (var index = 0; index < hirarchy.length; index++) {
position += '["'+ hirarchy[index] +'"]';
}
}
return data_structure[position];
}
while hirarchy is the array. I get the [position] as a string which is not working well.
how can I make a js function which builds the object path dynamically by an array?
var arr = ["userconfig", "general", "name"];
var dataStructure = arr.reduceRight(function (value, key) {
var obj = {};
obj[key] = value;
return obj;
}, 'myVal');
Ends up as:
{ userconfig : { general : { name : 'myVal' } } }
Note that you may need a polyfill for the reduceRight method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/ReduceRight
The below function will take an object to modify and an array filled with the properties needed:
function objPath(obj,path){
path.forEach(function(item){
obj[item] = {};
obj = obj[item];
});
}
var myobj = {};
objPath(myobj,["test","test2","test3"]);
console.log(myobj);
//outputs
Object {test: Object}
test: Object
test2: Object
test3: Object
The function loops over the array creating the new object property as a new object. It then puts a reference to the new object into obj so that the next property on the new object can be made.
JSFiddle
Recursive function
var array = ["userconfig", "general", "name"];
function toAssociative(array) {
var index = array.shift();
var next = null;
if (array.length > 0) {
next = toAssociative(array);
}
var result = new Array();
result[index] = next;
return result;
}