Covert object to array of combinations/objects - javascript

Using lodash or underscore. I'm trying to convert this object:
{
"variations": {
"versions": ["sport", "generic"],
"devices": ["mobile", "tablet"]
}
}
to this:
var variations = [{
"version": "sport",
"device": "mobile"
}, {
"version": "sport",
"device": "tablet"
}, {
"version": "generic",
"device": "mobile"
}, {
"version": "generic",
"device": "tablet"
}];
What's the best/shortest method to do this?

Not sure with lodash or undesrcore. But with simple jquery i have done this. take a look.
var object={
"variations": {
"versions": ["sport", "generic"],
"devices": ["mobile", "tablet"]
}
};
var variations=[];
$.each(object.variations.versions, function(i, j) {
$.each(object.variations.devices, function(k, l) {
variations.push({version:j,device:l});
});
});

I think you wanna set object key to new variable name and do combinations of inside object values.
<script type="text/javascript">
//here I created two object keys for more clear
var json ={
"variations": {
"versions": ["sport", "generic"],
"devices": ["mobile", "tablet"]
},
"another_variations": {
"versions": ["sport", "generic"],
"devices": ["mobile", "tablet"]
}
};
for(var i in json){
window[i] = []; //here window[variable] will make global variable
ver = Object.keys(json[i])[0];//Object.keys(json[i]) get object keys ~["versions","devices"]
dev = Object.keys(json[i])[1];
window[i].push(
{
[ver]:json[i].versions[0],
[dev]:json[i].devices[0]
},
{
[ver]:json[i].versions[0],
[dev]:json[i].devices[1]
},
{
[ver]:json[i].versions[1],
[dev]:json[i].devices[0]
},
{
[ver]:json[i].versions[1],
[dev]:json[i].devices[1]
});
}
console.log(variations); //here can call object key as a variable name if you
console.log(another_variations);//don't use `window[variable]` in above, this will print undefined error
</script>

Found a solution using: https://gist.github.com/wassname/a882ac3981c8e18d2556
_.mixin({
cartesianProductOf: function(args) {
if (arguments.length > 1) args = _.toArray(arguments);
// strings to arrays of letters
args = _.map(args, opt => typeof opt === 'string' ? _.toArray(opt) : opt)
return _.reduce(args, function(a, b) {
return _.flatten(_.map(a, function(x) {
return _.map(b, function(y) {
return _.concat(x, [y]);
});
}), true);
}, [
[]
]);
},
cartesianProductObj: function(optObj) {
var keys = _.keys(optObj);
var opts = _.values(optObj);
var combs = _.cartesianProductOf(opts);
return _.map(combs, function(comb) {
return _.zipObject(keys, comb);
});
}
});
See working:
https://jsfiddle.net/rickysullivan/5ryf9jsa/

Related

Get values for a matching key recursively from object

I have this json object
{
"data": {
"user": {
"user_info": {
"id": "AoGC2HQ9vedHmzcMX"
},
"product": [
{
"node": {
"id": "NzcxNzU2ODU1ODM1",
"feedback": {
"raters": {
"nodes": [
{
"id": "1",
"name": "Dan"
},
{
"id": "2",
"name": "Allen"
},
{
"id": "3",
"name": "Williams"
}
]
},
"commentors": {
"nodes": [
{
"id": "001",
"name": "Kent"
},
{
"id": "002",
"name": "Jay"
}
]
}
}
}
}
]
}
}
}
So how do I make it to get values of id If the parent property matches the desired key name, In this example I want to get all id's from raters.nodes only.
so expected result is
[1,2,3]
I know can do obj.data.user.product[0].node.feedback.raters.nodes and loop through that, but that is not how I want and the object tree occasionally changes.
I have used this recursive function
const recursiveSearch = (obj, searchKey, results = []) => {
const r = results;
Object.keys(obj).forEach(key => {
const value = obj[key];
if(key === searchKey && typeof value !== 'object'){
r.push(value);
}else if(typeof value === 'object'){
recursiveSearch(value, searchKey, r);
}
});
return r;
};
//returns all id's
While it works, it returns all id values, so how do I improve it? If not, how do I make this possible?
I think you want to really do this in 2 steps,..
First make a function to get the root node your looking for, and then you can just use map like normal.
Below is an example.
var data = JSON.parse("{\"data\":{\"user\":{\"user_info\":{\"id\":\"AoGC2HQ9vedHmzcMX\"},\"product\":[{\"node\":{\"id\":\"NzcxNzU2ODU1ODM1\",\"feedback\":{\"raters\":{\"nodes\":[{\"id\":\"1\",\"name\":\"Dan\"},{\"id\":\"2\",\"name\":\"Allen\"},{\"id\":\"3\",\"name\":\"Williams\"}]},\"commentors\":{\"nodes\":[{\"id\":\"001\",\"name\":\"Kent\"},{\"id\":\"002\",\"name\":\"Jay\"}]}}}}]}}}");
function getRoot(data, search) {
function get(path, data) {
for (const [k, v] of Object.entries(data)) {
if (v instanceof Object) {
const pp = `${path}.${k}`;
if (pp.slice(-search.length) === search) {
return v;
}
const r = get(`${path}.${k}`, v);
if (r) return r;
}
}
}
return get('', data);
}
const r = getRoot(data, 'raters.nodes');
console.log(r && r.map(i => i.id));

How to hide object property to display using angular ng-model?

I want to hide _id to display on UI using ng-model , I see alot of examples of filtering data using ng-repeat but i did not find angular solution to achieve this task using ng-model.How can hide _id property to display ?
main.html
<div ng-jsoneditor="onLoad" ng-model="obj.data" options="obj.options" ></div>
Ctrl.js
$scope.obj.data = {
"_id": "58a3322bac70c63254ba2a9c",
"name": "MailClass",
"id": "MailTask_1",
"createdBy": "tyuru",
"__v": 0,
"properties": [{
"label": "Java Package Name",
"type": "String",
"editable": true,
"binding": {
"type": "property",
"name": "camunda:class"
},
"$$hashKey": "object:29"
}],
"appliesTo": [
"bpmn:ServiceTask"
]
}
var json = {};
function loadCurrentUserAndTemplate() {
AuthService.getCurrentUser()
.then(function(resp) {
$scope.currentUser = resp.data.id;
// console.log($scope.currentUser);
userTemplate($scope.currentUser);
});
}
loadCurrentUserAndTemplate();
$scope.obj = {
data: json,
options: {
mode: 'tree'
}
};
var privateFields = removePrivateFields($scope.obj.data, ['_id', '__v']);
// add private fields back to $scope.obj.data before POST
var modifiedData = Object.assign({}, $scope.obj.data, privateFields);
function removePrivateFields(obj, props) {
var output = {};
props.forEach(function(prop) {
if (obj.hasOwnProperty(prop)) {
output[prop] = obj[prop];
delete obj[prop];
}
});
return output;
}
function userTemplate(user) {
// console.log('inside template',$scope.currentUser);
templateService.getUserTemplates(user)
.then(function(response) {
// console.log('userTemplate',response.data);
// console.log(response.data.length);
$scope.displayedTemplates = response.data;
if (response.data.length !== 0 && response.data !== null) {
$scope.obj.data = response.data[0];
}
}
you can create a function like removePrivateFields to strip the private fields from original object and attach them back to the modified object before submitting to server
// for testing
var $scope = { obj: {} };
var jsonData = {
"_id": "58a3322bac70c63254ba2a9c",
"name": "MailClass",
"id": "MailTask_1",
"createdBy": "tyuru",
"__v": 0,
"properties": [{
"label": "Java Package Name",
"type": "String",
"editable": true,
"binding": {
"type": "property",
"name": "camunda:class"
},
"$$hashKey": "object:29"
}],
"appliesTo": [
"bpmn:ServiceTask"
]
};
var privateFields = removePrivateFields(jsonData, ['_id', '__v']);
// private fields got removed form actual jsonData
$scope.obj.data = jsonData;
console.log($scope.obj.data);
// once edit
// add private fields back to $scope.obj.data before POST
var modifiedData = Object.assign({}, $scope.obj.data, privateFields);
console.log(modifiedData);
function removePrivateFields(obj, props) {
var output = {};
props.forEach(function(prop) {
if (obj.hasOwnProperty(prop)) {
output[prop] = obj[prop];
delete obj[prop];
}
});
return output;
}
It would be both more performant and along Angular best practices to instead delegate this functionality into your controller or the service fetching the object.
Ideally, you want to perform any object manipulation or formatting within an Angular service, but you could also do it within your controller (probably fine if you're just instantiating your JSON editor with mock data).

How to get the key value from nested object

I am having below object where I am trying to get all the id values.
[{
"type": "test",
"id": "100",
"values": {
"name": "Alpha"
},
"validations": []
}, {
"type": "services",
"validations": [{
"id": "200",
"name": "John",
"selection": [{
"id": "300",
"values": {
"name": "Blob"
}
}]
}]
}]
Using the below code, I am getting only the first id value. Is there any way to get all the id values from the nested object without using any external module.
for (var prop in obj) {
console.log(prop)
if (prop === key) {
set.push(prop);
}
}
Expected Output
[100,200,300] //all id values
You can use a JavaScript function like below to get the nested properties:
function findProp(obj, key, out) {
var i,
proto = Object.prototype,
ts = proto.toString,
hasOwn = proto.hasOwnProperty.bind(obj);
if ('[object Array]' !== ts.call(out)) out = [];
for (i in obj) {
if (hasOwn(i)) {
if (i === key) {
out.push(obj[i]);
} else if ('[object Array]' === ts.call(obj[i]) || '[object Object]' === ts.call(obj[i])) {
findProp(obj[i], key, out);
}
}
}
return out;
}
Check this Fiddle for a working solution.
Using Object.keys
function findProp(obj, prop) {
var result = [];
function recursivelyFindProp(o, keyToBeFound) {
Object.keys(o).forEach(function (key) {
if (typeof o[key] === 'object') {
recursivelyFindProp(o[key], keyToBeFound);
} else {
if (key === keyToBeFound) result.push(o[key]);
}
});
}
recursivelyFindProp(obj, prop);
return result;
}
// Testing:
var arr = [{
"type": "test",
"id": "100",
"values": {
"name": "Alpha"
},
"validations": []
}, {
"type": "services",
"validations": [{
"id": "200",
"name": "John",
"selection": [{
"id": "300",
"values": {
"name": "Blob"
}
}]
}]
}];
console.log(findProp(arr, "id"));
To get the keys from nested objects, you first need to put your code in a function, then for each of the top-level keys, check if it's an array or object. If it is, just call your function again from within that function (weird, I know.) Just make sure you don't skip the check of whether it's an object. You'll get stuck in an infinite loop. Something like this:
function parseObjectKeys(obj) {
for (var prop in obj) {
console.log(prop)
var sub = obj[prop]
if (typeof(sub) == "object") {
parseObjectKeys(sub);
}
}
}
Here's a more complex example:
https://jsfiddle.net/tfqLnzLm/1/
You can use a XPath styled json parser like JSONPath. The version I'm presenting here is a extended version I did here:
function jsonPath(obj,expr,arg){var P={resultType:arg&&arg.resultType||"VALUE",result:[],normalize:function(e){var t=[];return e.replace(/[\['](\??\(.*?\))[\]']/g,function(e,r){return"[#"+(t.push(r)-1)+"]"}).replace(/'?\.'?|\['?/g,";").replace(/;;;|;;/g,";..;").replace(/;$|'?\]|'$/g,"").replace(/#([0-9]+)/g,function(e,r){return t[r]})},asPath:function(e){for(var t=e.split(";"),r="$",a=1,n=t.length;n>a;a++)r+=/^[0-9*]+$/.test(t[a])?"["+t[a]+"]":"['"+t[a]+"']";return r},store:function(e,t){return e&&(P.result[P.result.length]="PATH"==P.resultType?P.asPath(e):t),!!e},trace:function(e,t,r){if(e){var a=e.split(";"),n=a.shift();if(a=a.join(";"),t&&t.hasOwnProperty(n))P.trace(a,t[n],r+";"+n);else if("*"===n)P.walk(n,a,t,r,function(e,t,r,a,n){P.trace(e+";"+r,a,n)});else if(".."===n)P.trace(a,t,r),P.walk(n,a,t,r,function(e,t,r,a,n){"object"==typeof a[e]&&P.trace("..;"+r,a[e],n+";"+e)});else if(/,/.test(n))for(var l=n.split(/'?,'?/),s=0,c=l.length;c>s;s++)P.trace(l[s]+";"+a,t,r);else/^\(.*?\)$/.test(n)?P.trace(P.eval(n,t,r.substr(r.lastIndexOf(";")+1))+";"+a,t,r):/^\?\(.*?\)$/.test(n)?P.walk(n,a,t,r,function(e,t,r,a,n){P.eval(t.replace(/^\?\((.*?)\)$/,"$1"),a[e],e)&&P.trace(e+";"+r,a,n)}):/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(n)&&P.slice(n,a,t,r)}else P.store(r,t)},walk:function(e,t,r,a,n){if(r instanceof Array)for(var l=0,s=r.length;s>l;l++)l in r&&n(l,e,t,r,a);else if("object"==typeof r)for(var c in r)r.hasOwnProperty(c)&&n(c,e,t,r,a)},slice:function(e,t,r,a){if(r instanceof Array){var n=r.length,l=0,s=n,c=1;e.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g,function(e,t,r,a){l=parseInt(t||l),s=parseInt(r||s),c=parseInt(a||c)}),l=0>l?Math.max(0,l+n):Math.min(n,l),s=0>s?Math.max(0,s+n):Math.min(n,s);for(var o=l;s>o;o+=c)P.trace(o+";"+t,r,a)}},eval:function(x,_v,_vname){try{return $&&_v&&eval(x.replace(/#/g,"_v"))}catch(e){throw new SyntaxError("jsonPath: "+e.message+": "+x.replace(/#/g,"_v").replace(/\^/g,"_a"))}}},$=obj;return expr&&obj&&("VALUE"==P.resultType||"PATH"==P.resultType)?(P.trace(P.normalize(expr).replace(/^\$;/,""),obj,"$"),P.result.length?P.result:!1):void 0}
// some extensions I have added to JSONPath
var jsonPathStore = function(obj,path,values) {
var maps=jsonPath(obj, path,{resultType:"PATH"})
maps.map(function(item,index) {
return eval( '(' + item.replace(/\$/,"obj") + '="' + values[index] +'"' + ')' );
})
}
var jsonPathDelete = function(obj,path) {
var maps=jsonPath(obj, path,{resultType:"PATH"})
maps.map(function(item,index) {
return eval( '(' + 'delete ' + item.replace(/\$/,"obj") + ')' );
})
}
var jsonPathRead = function(obj,path) {
var maps=jsonPath(obj, path,{resultType:"PATH"})
return maps.map(function(item,index) {
return eval( '(' + item.replace(/\$/,"obj") + ')' );
})
}
var jsonObject = [{
"type": "test",
"id": "100",
"values": {
"name": "Alpha"
},
"validations": []
}, {
"type": "services",
"validations": [{
"id": "200",
"name": "John",
"selection": [{
"id": "300",
"values": {
"name": "Blob"
}
}]
}]
}]
// this XPath will read all the id properties starting from the root element
console.log( "jsonPathRead All Ids" + JSON.stringify(jsonPathRead(jsonObject,"$..id"), null, 2) )
function getIds(obj) {
for (var x in obj) {
if (typeof obj[x] === 'object') {
getIds(obj[x]);
} else if (x === 'id') {
console.log(obj.id);
}
}
}

Creating an array in JavaScript from JSON file

My JSON file:
[{"val0":"Paul","val1":"Jake","val2":null,"val3":"Max"},
{"val0":"Sam","val1":"Tina","val2":"Emily","val3":"Hardwell"},
{"val0":"Tom","val1":"Julie","val2":null,"val3":"Adi"}]
I want to create an array in javascript as follows:
var dataSet=[
['Paul','Jake','null','Max'],
['Sam','Tina','Emily','Harwell'],
['Tom','Julie','null','Adi']
];
I tried the following code but it isn’t working. Can anybody please help?
$.getJSON("filename.json", function(data) {
var items = [];
$.each(data, function(key, val) {
items.push(val);
});
// …
});
I’m using this array for display purpose (using DataTables), so, I want to create the array in that format.I'm using the dataSet array for displaying in DataTables as follows:
var dataSet = [
['Paul','Jake','Isha','Mike','null','null','Parth','Tinker'],
['Tina','Michael','null','Blue','Red','','Emily','Mina']
];
$(document).ready(function() {
$('#demo').html( '<table cellpadding="0" cellspacing="0" border="0" class="display" id="example"></table>' );
$('#example').dataTable( {
"data": dataSet,
"columns": [
{ "title": "Name" },
{ "title": "Deadline" },
{ "title": "Additional fees" },
{ "title": "Requirements" },
{ "title": "Field" },
{ "title": "Award" },
{ "title": "Renewable requirements"},
{ "title": "Link" }
]
} );
} );
You get an array of objects, and you want an array of arrays, so convert each object to an array by reading the properties of the object:
var items = [];
$.each( data, function( key, val ) {
items.push([val.val0,val.val1,val.val2,val.val3]);
});
Try this
<script>
$(function() {
$.getJSON("filename.json", function(data) {
var items = [];
$.each(data, function(key, val) {
var tmp = [];
for (var Key in val) {
tmp.push(val[Key]);
}
items.push(tmp);
});
console.log(items);
});
});
A solution without jquery:
var data = [
{ "val0": "Paul", "val1": "Jake", "val2": null, "val3": "Max" },
{ "val0": "Sam", "val1": "Tina", "val2": "Emily", "val3": "Hardwell" },
{ "val0": "Tom", "val1": "Julie", "val2": null, "val3": "Adi" }
],
dataSet = data.reduce(function (r, a) {
var i, a0 = [];
for (i in a) {
a0.push(a[i]);
}
r.push(a0);
return r;
}, []);
document.getElementById('out').innerHTML = JSON.stringify(dataSet, null, 4);
<pre id="out"></pre>
One liner:
var dataSet = rawData.map(function(e){ return Object.keys(e).map(function(i){ return e[i]}); })
Output:
Output as JSON:
Method explanation (from Javascript Reference)
The map() method creates a new array with the results of calling a provided function on every element in this array.
The Object.keys() method returns an array of a given object's own enumerable properties

How to iterate through nested objects in a generic way

I am trying to fetch the value of the nested objects without using it's key. Like for example if I have a object like
var a = {"key" : "100"}
I don't want to use a.key, to get the result, though i have nested objects, it is becoming difficult for me to fetch the value this is what I have tried:
var Obj = [{"ghi":{"content":"abc"}},{"def":{"imgURL":"test.png"}},{"abc":{"key":"001"}},{"ghi":{"content":"abc"}},{"def":{"imgURL":"test.png"}},{"abc":{"key":"001"}}]
for(var key in Obj){
abc = Obj[key]
for(var j in abc){
def = abc[key]
}
}
So i need the values of all the objects, without using the key directly.
Maybe this helps
function getValues(array, key) {
var result = [];
array.forEach(function (a) {
a[key] && result.push(a[key]);
});
return result;
}
var array = [{ "ghi": { "content": "abc" } }, { "def": { "imgURL": "test.png" } }, { "abc": { "key": "001" } }, { "ghi": { "content": "abc" } }, { "def": { "imgURL": "test.png" } }, { "abc": { "key": "001" } }];
document.write('<pre>' + JSON.stringify(getValues(array, 'ghi'), 0, 4) + '</pre>');

Categories

Resources