For loop is not working with json data - javascript

I'm trying to make a loop in javascript with the following code. It's getting length from json data.
The console.log(albums.data.length); line is working and returning 3. Why the loop is not working then?
The console.log(x); is not returning anything, even not blank line.
There is also no error in console.
function getBestPhoto(albums){
console.log(albums);
console.log(albums.data.length);
for(var x in albums.data.length){
console.log(x);
for(var y in albums.data[x].photos.length){
console.log(y);
}
}
}
I have tried another type of loop(for(var i = 0; i < blabla; i++)) but its not working too.
Edit:
I wanna use
for(var x = 0; x < albums.data.length; x++){
console.log(albums.data[x].photos.id);
}
instead of
for(var x in albums.data){
How can i do it?

You should remove .length from loops
function getBestPhoto(albums){
console.log(albums);
console.log(albums.data.length);
for(var i = 0; i < albums.data.length; i++){
var x = albums.data[i];
console.log(x);
for(var j = 0; j < albums.data[i].photos.length; j++){
var y = albums.data[i].photos[j];
console.log(y);
console.log(albums.data[i].photos[j].id);
}
}
}

The for-in loop is not for arrays, it is for iterating over properties/fields of an object. If albums.data is an array, you should use the forEach loop statement instead. If albums.data is an object, and you are trying to access its properties/fields/attributes, you can use the for-in construct.
If albums.data is an array, try:
albums.data.forEach(function(element, index) {
// Here you have access to each element (object) of the "albums.data" array
console.log(element.toString());
// You can also access each element's properties/fields if the element is an
// object.
// If the element is an array itself, you need to iterate over its elements
// in another inner foreach.
// Here we are accessing the "photos" property of each element - which itself
// is another array.
element.photos.forEach(function(photo, index) {
// Here you have access to the elements of the "photos" array
// Each element of the "photos" array is put in the photo variable.
// Assuming each element of the "photos" array is an object, you can access
// its properties, using the dot notation:
console.log("photo id=", photo.id);
// If the property name (e.g. "id") is not a valid javascript name
// (has some special symbols), use the bracket notation
console.log("photo URL=", photo["photo-url"]);
});
});
You can also use the lodash library for this (and many other neat functionalities).
If albums.data is an object, try:
for (var prop in albums.data) {
// Again, this construct is for accessing properties of an object
// (e.g. if albums.data is an object), not an array.
console.log("property name=" + prop + ", " + "property value=" +
albums.data[prop]);
}

Related

I have an issue with removing an object key with a for in loop

I'm using a for x in loop to check if a value is == to [] and if so remove the property using remove but it just does not seem to work.
const whosOnline = (a) => {
var obj = { online:[],
offline:[],
away:[] };
for(let i = 0; i < a.length; i++){
if(a[i].lastActivity > 10 && a[i].status == 'online'){obj.away.push(a[i].username)}
else if(a[i].status == 'offline'){obj.offline.push(a[i].username)}
else{obj.online.push(a[i].username)}
}
for(let x in obj){
console.log(obj[x])
if(obj[x] === []){delete obj[x]}}
return obj
}
you were close, however you also need to reference the array index for each object key value. Comments explaining this in the code below.
var obj = { online:[],
offline:[],
away:[] };
for(var x in obj){
if(!obj[x][0]){ // The 0 is the index inside the online array, next loop it will be the offline array and then the away array.
console.log('The array is empty');
// Do what you want to do now that it is empty
// This will continue to loop through and check the value of all the keys in the object.
}
}
console.log('done');
Good luck -
Mitch from
https://spangle.com.au
Using some debugging (simply testing if a console.log gets printed for instance) you find that your if-condition is never true.
This is because you test if an array equals a newly created empty array. This can never be the case, because objects are compared by object reference instead of value.
Instead you want to probably test to see if your array is empty by doing ‘if(obj[x].length===0)’ (or shorter: ‘if(!obj[x].length)’)

Looping through variable names as strings, and destroying them

I have a list of variables (let's call them obj1, obj2, etc.). I would like to loop through all of them and, if they exist, destroy them. Obviously .destroy() is an external call.
Why does this work:
for (var i = 0; i < 10; i++) {
var obj = "obj" + i.toString();
if (window[obj]) {
window[obj].destroy();
}
}
But this doesn't:
var objs = [];
for (var i = 0; i < 10; i++) {
objs.push("obj" + i.toString());
if (objs[i]) {
objs[i].destroy(); //throws a TypeError
}
}
And is there a better solution that's more like the second, and doesn't involve accessing global scope via window? Please don't say eval().
objs.push("obj" + i.toString()); will push a string to the objs array. But strings don't have a .destroy property. In comparison, window["obj" + i.toString()] tries to reference a property on the window object by that name. (The value in that property, or undefined, will be pushed to objs)
It would be better to restructure your script so that rather than searching through the window object for variables of a certain name, you instead put all the related variables into an array at the start, so that you can then iterate through the array and destroy() them directly:
const objs = [
<someObj1>,
<someObj2>,
...
];
objs.forEach(obj => obj.destroy());
In the first example, you are using the string as the key to the object window, like this:
window.obj1
and then calling destroy on it.
The second example doesn't work because what you are pushing into the array is a string,
"obj" + i.toString()
You are calling destroy in the string itself since you created an array of strings. That's why you get the TypeError.
If you bother to use window object, why don't you clone it to a new object called container? That may work for you. Thanks
const container=window;
for (var i = 0; i < 10; i++) {
var obj = "obj" + i.toString();
if (container[obj]) {
container[obj].destroy();
}
}

Uncaught Type Error in javascript: object has no method

Uncaught TypeError: Object 0 has no method 'addEventListener'
var A={};
A.addEventsToClassName=function(event,className,func)
{
var a=document.getElementsByClassName(className);
for(var b in a)
{
b.addEventListener(event,func,false);
}
};
Object b is meant to be an element object once the function is called later in the code. How can I prevent this error?
A for (var b in a) will give the property names within a, not the actual values; so you need to dererefence a when you want to use them.
a[b].addEventListener(event, func, false);
Also, it's an Array like data structure, so you should iterate it as such:
for (var i = 0; i < a.length; ++i) {
a[i].addEventListener(event, func, false);
}
The b is probably a index not your object . Perhaps you want write like this:
a[b].addEventListener(event,func,false);
b is not an object nor an element, it is a string ("0"). for...in gives you the keys not the value.
Don't use for(var b in a) to loop through a NodeList (it will loop through not only the properties of itself but also the properties inherited from its parent), do this instead:
for(var i = 0; i < a.length; a++){
a[i].addEventListener...
}
If you ask why, then take this for example,
for(var a in document.querySelectorAll("body")){
console.log(a);
}
>"0"
>"length"
>"item"
You can see that for...in does not work in this case since length and item are not actually in the list but still properties inherited.

Javascript object containing array of comma separated coordinates

What's the correct format for an object containing an array of comma separated numbers?
Here is what I am doing, but I am unsure if it is the correct way:
var myObj = {
'coord1' : { 'section-a' : [216,259,216,294,165,294,165,259,216,259] },
'coord2' : { 'section-a' : [20,218,8,178,3,143,6,112,13] }
};
I'd like to access the coordinates of a section by the following:
for(var coord in myObj){
for(var section in coord){
alert(section);
}
}
And have the raw coordinates returned as a comma separated string. Any suggestions?
Unfortunately for in loops don't do quite what you're expecting.
The variable that you create is property name of the current iteraton when you iterate over an object. It is the index of the array when you iterate over an array.
for(var prop in myObj){
for(var i in myObj[prop]){
alert(myObj[prop][i]);
}
}
Note, when iterating over objects you may only want to iterate on direct properties of that object, not properties up the protype chain. Use hasOwnPrototype if you only want to iterate over direct properties on the object.
for(var prop in myObj){
if(myObj.hasOwnProperty(prop)) {
for(var i in myObj[prop]){
if(myObj[prop].hasOwnProeprty(i)) {
alert(myObj[prop][i]);
}
}
}
}
Remember that a for in loop in javascript returns an objects property key not the object the key refers to. Also use .hasOwnProperty to avoid possibly looping over an objects prototype.
You would need to change it to:
for (var coord in myObj){
if(myObj.hasOwnProperty[coord]){
var coord = myObj[coord];
for(var section in coord)
if(coord.hasOwnProperty[section]){
alert(coord[section]);
}
}
}
}

Parse 2 dimensional JSON array in Javascript

I have a two dimensional JSON array where each element contains several attributes. The example below is intentionally simplified:
var map_data = { "1":
{"1":{"name":"aa"},"2":{"name":"bb"}},
"2":
{"1":{"name":"cc"},"2":{"name":"dd"}}
};
I try to parse the data but .length doesn't work:
for(x=1; x<=map_data.length; x++) {
for(y=1; y<=map_data[x].length; y++) {
// CODE
}
}
Many, many thanks!
That's not an array, they are simple objects, that's why you cannot use the length property.
You need to use the for...in statement:
for(var x in map_data) {
if (map_data.hasOwnProperty(x))
for(var y in map_data[x]) {
if (map_data[x].hasOwnProperty(y)) {
// CODE
}
}
}
The hasOwnProperty checks are because this statement iterates over all properties, inherited or not, and if something (like some JavaScript frameworks) augmented the Array.prototype or Object.prototype objects, those augmented properties will be also iterated.
You should know that this statement doesn't ensure anyhow the order of iteration.
I would recommend you to use a "real" array:
[
[{"name":"aa"},{"name":"bb"}],
[{"name":"cc"},{"name":"dd"}]
]
In this way you will be able to use the length property to iterate over the indexes.
hasOwnProperty is used to determine whether an object has the specified property as a direct property of that object with no respect to it's prototype chain.
for(var i in map_data){
if(map_data.hasOwnProperty(i)){
for(var j in map_data[i]){
if(map_data[i].hasOwnProperty(j)){
/*do whatever you want with map_data[i][j]*/
}
}
}
}
Since map_data is an object instead of an array you need to use for/in loop:
for (var x in map_data) {
// check for hasOwnProperty omitted for simplicity.
for (var y in map_data[x]) {
// CODE.
}
}
But it's better to send that JSON as an array [a,b,c] instead of an object {"0":a,"1":b,"2":c}.
Use the for .. in construct:
for (var m in map_data) {
// ...
}
Also, I must note that this isn't a "JSON array", but rather a nested object. JSON is just the string representation of nested JS objects and arrays.
if it helps someone, its a example of c# and javascript:
c#:
List<List<string>> list_array = new List<List<string>>();
JavaScriptSerializer jss = new JavaScriptSerializer();
string _myJSONstring = jss.Serialize(list_array);
/*in this case list_array is a list bidimensional, but can be a single array,
if you print _myJSONstring, this will show like this: "[["XX","AAAA"],["YY","BBBB"]]" */
javascript:
into a function that get the string from c#:
var a = JSON.parse(array);
for (var t = 0; t < array.length; t++) {
for (v = 0; v < array[t].length; v++) {
alert(array[t][v]);
}
}

Categories

Resources