simplifying a nested javascript object - javascript

I have an object that looks like this:
var someUglyObject =
{
"1-1" : {foo1: "foo1-1Value", bar1: "bar1-1value"},
"1-2" : {foo2: "foo1-2Value", bar2: "bar1-2value"},
"2-1" : {foo2: "foo2-1Value", bar2: "bar2-1value"},
"2-2" : {foo2: "foo2-2Value", bar2: "bar2-2value"}
}
I need to simplify the nested object above and convert into a simpler object after some processing (concatenation) like below:
var myObj = {
"1": { propsTogether : "foo1-1Valuebar1-1valuefoo1-2Valuebar1-2value"},
"2": { propsTogether : "foo2-1Valuebar2-1valuefoo2-2Valuebar2-2value" }
}
My plan is to interate through the keys like this, but not sure how to group the props together based on the first char of the key , i.e. for a key with value of '2-1' - 2 should be the new key.
var myObj= {};
Object.keys(someUglyObject).forEach(function(key) {
}

You can use Object.keys and reudce
Here idea is
First get the keys out of object.
Sort them // Object don't have order
Now split key on - and use first element as key on op object.
Use object.values and join them in desired format and place it on respective key
var obj = {'1-1' : {foo1: "foo1-1Value", bar1: "bar1-1value"},'1-2' : {foo2: "foo1-2Value", bar2: "bar1-2value"},'2-1' : {foo2: "foo2-1Value", bar2: "bar2-1value"},'2-2' : {foo2: "foo2-2Value", bar2: "bar2-2value"}}
let op = Object.keys(obj).sort().reduce((op,inp)=>{
let key = inp.split('-',1)[0]
op[key] = op[key] || {props:''}
op[key].props = op[key].props + Object.values(obj[inp]).join('')
return op
},{})
console.log(op)

Related

how to get key names and length of nested json's in java script

Using JavaScript, I get the following JSON from my API.
abc: {
a: {
name: "ascs"
},
b: {
name: "sddd"
},
c: {
name: "wede"
}
}
I need to find following:
How do calculate length of json inside abc JSON ?
How do i get keys name [a,b,c] from abc JSON ?
if i have another json :
data : {
"5.5": {
name :"bhagvat"
}
}
in above case how do i get the value of name ?
(how to deal with float keys)? i try with ===> data."5.5".name
You can use Object.keys() to get the keys of object and then use .length for number of json inside abc json.
var abc = {
a: {
name : "ascs"
},
b : {
name : "sddd"
},
c: {
name :"wede"
}
};
var keys = Object.keys(abc);
var length = keys.length;
console.log('key is ',keys);
console.log('length is '+length);
To get the key names you can use Object.keys().
const abc = {
a: {
name : "ascs"
},
b : {
name : "sddd"
},
c: {
name :"wede"
}
}
const abcKeyNames = Object.keys(abc);
This will return an array of key names in the object.
Not sure what you mean by length of object but I think you mean how many keys are in this object? you can use Array.length()
const abcLength = abcKeyNames.length()
This will return how many elements are in this array.
Using spread operator,
let keys = [...abc];
console.log(keys.length); // to get keys length in json
console.log(keys); //to get the keys
Use Object.keys
let abc = { a: {name: "ascs"},b: {name: "sddd"},c: {name: "wede"}};
let keys = Object.keys(abc);
console.log(keys); // paints keys
let length = keys.length;
console.log(length); // paints the number of keys
EDIT
To extract the value you bracket notation
let data = {5.5 : {name: "bhagvat"}};
console.log(data["5.5"].name);
Object.keys
let data = { "10.5": {"XYZ": "ABC"},"10.6": {"PQR": "LMN"}};
let keys = Object.keys(data);
console.log(keys); // ["10.5","10.6"]
let length = keys.length;
console.log(length); // 2
For accessing element using float key
let xyz = data["10.5"];
Get this json in "var data" then the folloing answers works :
how do calculate length of json inside abc JSON ?
Ans : Object.keys(data.abc).length;
how do i get keys name [a,b,c] from abc JSON ?
Ans : data.abc.a["name"]
data.abc.b["name"]

JavaScript - retrieve value from nested object, using array of keys

How can I get a value from a nested object, using an array of keys?
// my sample object
var obj = {
type : "Purchase",
category : "Apartment",
categoryOptions : {
apartment : {
floors : {
type : "number",
value : null,
placeholder : "Total Floors"
},
},
},
}
var keysArray = ["value", "floors", "apartment", "categoryOptions"]
I tried to use array.reduceRight to achieve this but could not make it work.
here is what I've tried :
var roadToValue = keysArray.reduceRight(
function(previousValue, currentValue){
return previousValue + "[" + currentValue + "]" ;
}
);
// above function results in a single string like
// "categoryOptions[apartment][floors][value]"
// which off-course can't be used as object key
// and obj[roadToValue] results in 'undefined'
is there any way so I can get the proper key to pass to obj here?
You definitely can use reduceRight for this. The problem is that you created a string, however you need to pass your object as initialValue and use the squared bracket notation:
var obj = {"type":"Purchase","category":"Apartment","categoryOptions":{"apartment":{"floors":{"type":"number","value":null,"placeholder":"Total Floors"}}}}
var keysArray = ["value", "floors", "apartment", "categoryOptions"]
var value = keysArray.reduceRight((r, e) => r[e] || r, obj)
console.log(value)

looping through javascript objects

I have an array which contains many objects(all this data will come via ajax call, for example lets say there are only 3 records).
data : [{name : "a",id : "100"},{name : "b",id : "101"},{name : "c",id : "100"}];
Is there any way to loop through entire array and find objects with same id and concatenate their names and filter the array to be like this
data : [{name : "a,c",id : "100"},{name : "b",id:"101"}]
Thanks
You can use forEach() loop and check if id exists and concat name to that value.
var data = [{name : "a",id : "100"},{name : "b",id : "101"},{name : "c",id : "100"}];
var result = []
data.forEach(function(e) {
//Check if property with current object id exists in object provided as thisArg param and if it doesn't exists set its value to current object and push it to result array
if(!this[e.id]) this[e.id] = e, result.push(this[e.id])
// if it does exists then concat name of current object to name of existing one that had the same id
else this[e.id].name += ',' + e.name
}, Object.create(null))
console.log(result)
I suggest to use a hash table, which is used as a closure of the callback function. Then iterate over the objects and thest if the hash exists or not. If it exists, add the name to the name property of the object, otherwise create a new object with the actual data and push it to the result set.
Return the temporary array in Array#reduce.
var data = [{name : "a",id : "100"},{name : "b",id : "101"},{name : "c",id : "100"}];
data = data.reduce(function (hash) {
return function (r, a) {
if (hash[a.id]) {
hash[a.id].name += ',' + a.name;
} else {
hash[a.id] = { name: a.name, id: a.id };
r.push(hash[a.id]);
}
return r;
};
}(Object.create(null)), []);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Compare objects containing arrays

I have two JS objects which contain some arrays. I'd like to compare the two objects and create a third object, containing arrays only unique to secondObj.
They look like this:
firstObj : {
Jim_Array : [...],
Joe_Array : [...],
Bill_Array : [...]
}
secondObj : {
Bill_Array : [...],
Sam_Array : [...],
Kate_Array : [...],
Jim_Array : [...],
Joe_Array : [...]
}
I'd like to compare the two objects and end up with the following:
thirdObj : {
Sam_Array : [...],
Kate_Array : [...]
}
You can try something like following
var thirdObj = {};
for (var key in secondObj) {
if(!firstObj.hasOwnProperty(key)) {
// In case you need to compare the array additional check will come here
thirdObj[key] = secondObj[key];
}
}
Another way
var thirdObj = {};
for (var key in secondObj) {
if(firstObj[key] === undefined) {
// In case you need to compare the array additional check will come here
thirdObj[key] = secondObj[key];
}
}
You can use Object.keys() with reduce() and check if firstObj has property of secondObj with hasOwnProperty(), if not add to new object.
var firstObj = {Jim_Array : ['...'], Joe_Array : ['...'], Bill_Array : ['...']}
var secondObj = {Bill_Array : ['...'], Sam_Array : ['...'], Kate_Array : ['...'], Jim_Array : ['...'], Joe_Array : ['...']}
var result = Object.keys(secondObj).reduce(function(o, e) {
if(!firstObj.hasOwnProperty(e)) o[e] = secondObj[e];
return o;
}, {});
console.log(result)
A solution using underscore:
var result = _.pick(secondObj, _.difference( _.keys(secondObj), _.keys(firstObj)));

How to break up an object with a string of values to create a new array of objects?

I was working on a solution to another question posed, and I came up with a solution, but I'm convinced that there's a more elegant way to do it. Let's say that you have an object where all of the values are a string of values separate by commas, like this:
{ "action" : "goto,goto", "target" : "http://www.google.com,http://www.cnn.com" }
But, you'd like to separate the values and break up the object into an array of objects, like this:
[
{ "action" : "goto", "target" : "http://www.google.com" },
{ "action" : "goto", "target" : "http://www.cnn.com" }
]
Here's what my solution was:
var actions = obj.action.split(',');
var targets = obj.target.split(',');
// combined the actions and targets arrays
var combinedData = _.zip(actions, targets);
// go through the combinedData array and create an object with the correct keys
var commandList = _.map(combinedData, function(value) {
return _.object(["action", "target"], value)
});
This does what I want and doesn't look terrible, but is there a slicker way of accomplishing this?
Functional style is great. Here's a more direct approach.
var newObjects = [];
for(var k in o) {
var vals = o[k].split(',');
for(var i = 0, len = vals.length; i < len; i++) {
newObjects[i] = newObjects[i] || {};
newObjects[i][k] = vals[i];
}
}
I wouldn't worry too much about the implementation until you come up with a nice, compact, semantic name for this operation. Any ideas?
So, I did a little refactoring of my code to create a more functional and cleaner looking answer:
var obj = { "action" : "goto,goto", "target" : "http://www.google.com,http://www.cnn.com" }
// separate and split the values form the object
function separate(obj) {
return _.map( _.values( obj ), function(value) {
return value.split(',');
});
}
// returns [[ "goto", "goto"], ["http://www.google.com", "http://www.cnn.com"]]
// call separate and recombine the values with zip
function separateAndRecombine(obj) {
return _.zip.apply(_, separate(obj));
}
// returns [[ "goto", "http://www.google.com"], ["goto", "http://www.cnn.com"]]
// accept an object that has properties with a string of values
// separated by commas, and separate the values to create an array of objects
function unwind(obj) {
return _.map( separateAndRecombine(obj), function(value) {
return _.object(_.keys(obj), value)
});
};
/* returns:
[{ "action" : "goto", "target" : "http://www.google.com" },
{ "action" : "goto", "target" : "http://www.cnn.com" }] */
Now, unwind() will take an object with any number of properties or values and 'unwind' all of the existing properties.

Categories