I'm working with Json Object:
var someobj = {
'key':'value',
'key':'value',
'objectkey':{'key':'value','key':'value'}
}
While iterating, i want the result in console.log as:
KEY: key && VALUE: value
KEY: key && VALUE: value
OKEY: key && OKEYVALUE: value
While iterating I only get the first level, I can't seem to get it into the values that are the objects. I guess some sort of length could work:
EDIT2: Now with this inner loop it iterates and I get letters for external values, the inner values get logged completely.
var registration_form = {
'registration_form':{
'Display Name':'input',
'Username':{'inpute':'text','id':'some_id'},
'Password':'input',
'Email':'input',
'Captcha':'input'
}
};
function iterateNodes(data) {
for (var key in data){
var obj = data[key];
for(var prop in obj){
if(obj.hasOwnProperty(prop)){
var inobj = obj[prop];
for(var prop in inobj){
console.log(inobj[prop])
}
}else{
console.log(obj)
}
}
}
}
iterateNodes(registration_form);
In general you can iterate over properties of an object in this way:
for (var k in o) {
if (o.hasOwnProperty(k)) {
console.log('k: ' + k + ', v: ' + o[k])
}
}
so you can use recursion to go deeper than one level
function hasproperty(o) {
if (typeof o === 'object') {
for (var k in o) {
if (o.hasOwnProperty(k)) {
return true;
}
}
}
return false;
};
function iterate(o) {
for (var k in o) {
if (o.hasOwnProperty(k)) {
if (hasproperty(o[k])) {
console.log('within ' + k);
iterate(o[k]);
console.log('exit ' + k);
} else {
console.log('K: ' + k + ', V:' + o[k]);
}
}
}
};
Please try this out:
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
var someobj = {
'key1':'value1',
'key2':'value2',
'objectkey3':{'key01':'value01','key02':'value02'}
};
jQuery.each(someobj, function(i, val) {
if (typeof val == 'string'){
console.log("key : "+i+" value: "+val);
}else{
jQuery.each(val, function(j, val2) {
console.log("key : "+j+" value: "+val2);
});
}
});
</script>
Related
I have an object which has inner objects and properties defined like this:
var obj = {obj1 : { "prop1" : "nothing", "prop2" : "prop"},
obj2 : {"prop1" : "nothing", "prop2" : "prop"},
pr1 : "message",
pr2 : "mess"
};
Normally to iterate every property of an object , the for .. in loop can do the trick
for (property in obj){
if (obj.hasOwnProperty(property)){
console.log(property + " " + obj[property]);
}
}
the console displayed :
obj1 [object Object]
obj12 [object Object]
pr1 message
pr2 mess
However how to iterate the inner objects (obj1, obj2) and their own properties (prop1,prop2) ?
Recursion is your friend:
function iterate(obj) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object")
iterate(obj[property]);
else
console.log(property + " " + obj[property]);
}
}
}
Note: don't forget to declare property locally using var!
That's great anwsers, although the array cases is not covered, here's my contribution:
var getProps = function (obj) {
for (var property in obj) {
if (obj.hasOwnProperty(property) && obj[property] != null) {
if (obj[property].constructor == Object) {
getProps(obj[property]);
} else if (obj[property].constructor == Array) {
for (var i = 0; i < obj[property].length; i++) {
getProps(obj[property][i]);
}
} else {
console.log(obj[property]);
}
}
}
}
getProps(myObject);
To simply display the object structure, I often use: console.log (JSON.stringify (obj))
You can use recursion to achieve that:
function Props(obj) {
function getProps(obj){
for (var property in obj) {
if (obj.hasOwnProperty(property)){
if (obj[property].constructor == Object) {
console.log('**Object -> '+property+': ');
getProps(obj[property]);
} else {
console.log(property + " " + obj[property]);
}
}
}
}
getProps(obj);
}
see http://jsfiddle.net/KooiInc/hg6dU/
My application calls the module to parse nested JSON object, to read values of 2 keys.
parseData(str, function (error, str) {
if (err) {
console.log("Error - parseData : ", err);
} else {
console.log(str);
}
And the parseData module is as follows
function parseData(str, callback) {
function recursiveFunction(obj) {
var keysArray = Object.keys(obj);
for (var i = 0; i < keysArray.length; i++) {
var key = keysArray[i];
var value = obj[key];
if (value === Object(value)) {
parseData(value);
} else {
if (key == 'title') {
title = value;
}
if (key == 'extract') {
var extract = value.replace(/(\r\n|\n|\r)/gm," ");
callback(null, JSON.stringify('{"title":'+ title + ', "text":' + extract));
}
}
}
}
recursiveFunction(str);
}
But it shows following error
/modules/parseData.js:22
callback(null, JSON.stringify('{"title":'+ title + ', "text":' + extract));
^
TypeError: callback is not a function
Why is callback failing ? How to return back JSON object ?
EDIT
There were some errors in the code and now corrected.
function parseData(str, callback) {
function recursiveFunction(obj) {
var keysArray = Object.keys(obj);
for (var i = 0; i < keysArray.length; i++) {
var key = keysArray[i];
var value = obj[key];
if (value === Object(value)) {
recursiveFunction(value);
} else {
if (key == 'title') {
title = value;
}
if (key == 'extract') {
var extract = value.replace(/(\r\n|\n|\r)/gm," ");
callback(null, JSON.stringify('{"title":'+ title + ', "text":' + extract));
}
}
}
}
recursiveFunction(str);
};
You're calling parseData(value); and not passing a callback; pass callback if you want that original callback to be used.
I'm trying to extend js native array inside angular service to add some extra features without prototyping global objects.
app.factory('Collection', function($http, $q) {
var Collection = function(arr) {
this.key = 'id';
this._last = 0;
this._first = 77777777; //just big number.
this.append(arr);
}
Collection.prototype = new Array;
Collection.prototype.orderBy = function(n, reverse) {
if (reverse) {
this.sort(function(a, b) {
return b[n] - a[n];
})
} else {
this.sort(function(a, b) {
return a[n] - b[n];
})
}
}
Collection.prototype.spliceBy = function(key, val) {
for (var i = 0; i < this.length; i++) {
if (this[i][key] !== val) {
this.splice(i, 1); ///THIS NEVER HAPPENS !!
console.log('removed ' + i + ' from ', this);
}
}
}
Collection.prototype.subset = function(key, val) {
return this.filter(function(v) {
return (v[key] === val);
});
}
Collection.prototype.add = function(obj) {
for (var i = 0; i < this.length; i++) {
if (this[i][this.key] > this._last) {
this._last = this[i][this.key];
}
if (this[i][this.key] < this._first) {
this._first = this[i][this.key];
}
if (this[i][this.key] === data[this.key]) {
if (override) {
this[i] = data;
console.log('updated uniquePush');
}
return i;
break;
}
}
var id = this.push(data) - 1;
data._index = id;
return id;
}
return collection
});
This is working fine except for the spliceBy function.
I need to filter out elements that does not have value = x;
For example in my controller
.controller(function($scope,Collection){
$scope.posts = new Collection;
$scope.posts.add({id:1,type:'post'});
$scope.posts.add({id:2,type:'comment'});
//Collection is now [{id:1,type:post},{id:2,type:comment}];
//i want to remove all comments from array
$scope.posts.spliceBy('type','comment');
});
Yet nothing happens when calling spliceBy :*(
The spliceBy function will not work if you have two elements to remove in a row, because splice is updating the indexes from i to array.length. Try this instead:
Collection.prototype.spliceBy = function(key, val) {
var i = this.length;
while (i--) {
if (this[i][key] !== val) {
this.splice(i, 1); ///THIS NEVER HAPPENS !!
console.log('removed ' + i + ' from ', this);
}
}
}
In this DEMO you can see the red <b> tags are showing a different index from the black ones below, this happens why I am trying to use the same index for both <li> and parents <ul>, but something is not working properly... it seems like, only at the very first step, the index counting in skipped and all the remaining index then is "slipped" one step forward, so they are not matching...
var object = {
sometdhing: {
sometfhing: {
somgething: 'text',
someathing: 'text'
},
someathing: {
somefthing: 'text',
sometghing: 'text'
}
},
someathing: {
somethfing: {
somgething: 'text',
somethihng: 'text'
},
somejthing: {
somethhing: 'text',
somfething: 'text'
}
}
}
var indexes = [];
var object2ul = function (data, level) {
var keys = Object.keys(data);
var json = '<ul>'+ '<b style="color:red">'+level+'</b>';
for (var i=0; i<keys.length; ++i) {
var key = keys[i];
indexes.push(i);
json += '<li>' + "<b>" + indexes.join('_') + "</b> - " + key;
if (typeof(data[key]) === 'object') {
json += object2ul(data[key], indexes.join('_'));
} else {
json += '<ul><li>' + data[key] + "</li></ul>";
}
json += "</li>";
indexes.pop();
}
return json + "</ul>";
}
document.body.innerHTML = object2ul(object, 0);
Please help...
Css did help
Code: http://jsfiddle.net/18obnr9L/3/
here i construct elements from object like ul, li, ol...
var data = {
sometdhing: {
sometfhing: {
somgething: 'atext1',
someathing: 'atext2'
},
someathing: {
somefthing: 'atexta1',
sometghing: 'atexta2'
}
},
someathing: {
somethfing: {
somgething: 'btext1',
somethihng: 'btext2'
},
somejthing: {
somethhing: 'btexta1',
somfething: 'btexta2'
}
}
};
list(data);
function list(data) {
var ul = document.createElement('ol'),
li = document.createElement('li')
main = ul.cloneNode();
getProps(main, data);
document.body.appendChild(main);
function getProps(parent, d) {
for (var i in d) {
if (typeof d[i] == "string") {
addLi(parent, d[i], i);
} else if (d[i] instanceof Object) {
var pli = addLi(parent, '', i);
var temp = ul.cloneNode();
getProps( temp, d[i] )
pli.appendChild(temp);
parent.appendChild(pli);
}
}
}
function createUli(val){
var ul = document.createElement('ul');
var l = li.cloneNode();
ul.appendChild(l);
l.innerText = val;
return ul;
}
function addLi(p, val, i) {
var ele = li.cloneNode();
ele.innerText = i;
if (val != '') ele.appendChild(createUli(val));
p.appendChild(ele);
return ele;
}
}
I have a json object which looks like this:
var testJ = {"ROOT":{
dir : 'app',
files : [
'index.html',
{
dir : 'php',
files: [
'a.php',
{
dir : 'extras',
files : [
'a.js',
'b.js'
]
}
]
}
]
}};
I need to extract all the files and append into an array (index.html,a.php,a.js..etc)
For this I wrote a javascript code as follows:
var arr=[];
function scan(obj,append)
{
var k;
if (obj instanceof Object) {
for (k in obj){
if (obj.hasOwnProperty(k)){
if(k=='files')
{
scan( obj[k],1 );
}
}
}
} else {
body += 'found value : ' + obj + '<br/>';
if(append == 1)
arr.push(obj);
alert("Arr"+ arr);
};
};
scan(testJ,0);
I am not able to figure out where am I going wrong. Could some give me pointers?
var res = [];
function gather(j) {
for (var k in j) {
if (k === 'files') {
addFiles(j[k]);
} else if (typeof j[k] === 'object') {
gather(j[k]);
}
}
}
function addFiles(f) {
for (var i = 0; i < f.length; i++) {
if (typeof f[i] === "string") {
body += 'found value : ' + obj + '<br/>';
res.push(f[i]);
} else {
gather(f[i]);
}
}
}
gather(testJ);
Free tips:
instanceof is some cancerous stuff. Why does instanceof return false for some literals?
Always, always use === for comparison, not ==
I also wouldn't blindly use hasOwnProperty unless you're afraid the thing you're operating on might have a modified prototype, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in just for simplicity.
How about a map reduce approach?:
function mapJ(subject) {
return subject.files.map(function(item) {
if (typeof item === "string") {
return item;
} else {
return parseJ(item);
}
});
}
function reduceJ(subject) {
return subject.reduce(function(prev, cur) {
return prev.concat(cur);
}, []);
}
function parseJ(subject) {
return reduceJ(mapJ(subject));
}
var result = parseJ(testJ));