Javascript for in loop - javascript

var myArray = new Array();
var increment = 0;
myArray.push('Tom Hanks', 'Pierce Brosnan', 'Will Smith', 'Richard Ayoade');
for (actor in myArray) {
console.log(actor + ' is my #' + increment + ' choice.');
increment++;
}
Something is wrong with this for loop, and I believe its 'actor' in the for-in loop. This prints out a number where the name of the actor should be.
Coming from Ruby, this looks like a .each method iterating over each element in the array, but obviously this is going about things a bit differently. Can anyone explain why this isn't working?
Just picked up JS today. Thanks.

Thats not how for ... in works. From that link:
A for...in loop iterates over the properties of an object in an arbitrary order
And:
for..in should not be used to iterate over an Array where index order is important. Array indexes are just enumerable properties with integer names and are otherwise identical to general Object properties. There is no guarantee that for...in will return the indexes in any particular order and it will return all enumerable properties, including those with non–integer names and those that are inherited.
Given that you are passing in an array the properties are the indexes for the items it holds.
This is why you are getting the index and not the name.
If you want to retain order and print the names, you need a "traditional" for loop, like so:
for (var i = 0; i < myArray.length; i++) {
console.log(myArray[i] + ' is my #' + (i+1) + ' choice.');
}
The reason to be careful when using for .. in is it can have unexpected results. Checkout this jsFiddle...
var myArray = new Array();
var increment = 0;
myArray.push('Tom Hanks', 'Pierce Brosnan');
myArray.hello = "what?";
for (actor in myArray) {
alert(actor + ' is my #' + increment + ' choice.');
increment++;
}
for (var i = 0; i < myArray.length; i++) {
alert(myArray[i] + ' is my #' + (i+1) + ' choice.');
}
In this example, the first loop will iterate 3 times, picking up the 'hello' property as well as the rest in the array. While the second only does the 2 formal items in the array.

In that case, the correct code should be
var myArray = new Array(); var increment = 0;
myArray.push('Tom Hanks', 'Pierce Brosnan', 'Will Smith', 'Richard Ayoade');
for (actor in myArray) {
console.log(myArray[actor] + ' is my #' + increment + ' choice.');
increment++; }
it prints out
Tom Hanks is my #0 choice.
Pierce Brosnan is my #1 choice.
Will Smith is my #2 choice.
Richard Ayoade is my #3 choice.

You are seeing the index of the array element.
Remember that arrays are objects.
When using for(var item in object), var item is the key(property) associated with the value.
You are accessing the arrays properties(indexes), not values.
You should consider using the Array Objects buitin method forEach.
myArray.forEach(function(actor)){
console.log(actor + ' is my #' + increment + ' choice.');
increment++;
});

The simple answer is this: for in loops iterate over properties of an object. An array in JavaScript is an object that's indexed. So, your example is actually this:
Array[4]
0: "Tom Hanks"
1: "Pierce Brosnan"
2: "Will Smith"
3: "Richard Ayoade"
length: 4
__proto__: Array[0]
When you use your for/in code,
for (actor in myArray) {
console.log(actor + ' is my #' + increment + ' choice.');
increment++;
}
actor is the property at the time of iteration (0, 1, 2, 3...)
To access the value in your for in loop would require your code to be updated like this:
for (idx in myArray) {
console.log(myArray[idx] + ' is my #' + idx + ' choice.');
}
However, it's considered bad practice to use for in loops to iterate an array. For example, what if I did something like this:
myArray.type = "Actors";
The console log would return something like:
// 'Actors is my type choice'
Probably not the intended output. Instead, for array iteration, take a look at the for loop or forEach method of arrays.
for (var increment = 0, len = myArray.length; increment < len; increment += 1) {
console.log(myArray[increment] + ' is my #' + increment + ' choice.');
}
// or...
myArray.forEach(function(actor, increment) {
console.log(actor + ' is my #' + increment + ' choice.');
});

Related

JavaScript Looping Variables on Left Side of Equal Sign

I'm looping through results and writing them out to html.
I want to increment the number 1 on the lest side of the equal sign - the binding -
A_Inside_Bus_1_div, A_Inside_Bus_2_div, A_Inside_Bus_3_div etc..
How should I go about that?
for (var i = 0; i <= 4; i++) {
A_Inside_Bus_1_div.innerText = i + ". " + snapshot.child("0/A_Inside_Bus " + i).val();
A_Inside_Bus_1_Comments_div.innerText = snapshot.child("0/A_Inside_Bus " + i + " Comments").val();
}
Do it like this:
var A_Inside_Bus_div = [];
var A_Inside_Bus_Comments_div = [];
Before you continue the rest, like editing .innerHTML, you need to create those objects. Only after that you can do something like:
for (var i = 0; i <= 4; i++) {
A_Inside_Bus_div[i].innerText = i + ". " + snapshot.child("0/A_Inside_Bus " + i).val();
A_Inside_Bus_Comments_div[i].innerText = snapshot.child("0/A_Inside_Bus " + i + " Comments").val();
}
This is just an idea how you "should go" about that, as you said.
If those variables are actually the IDs of DIVsm and you're depending on the fact that IDs are turned into global varables, you can use document.getElementById() to access them.
for (var i = 0; i <= 4; i++) {
document.getElementById('A_Inside_Bus_' + (i+1) + '_div').innerText = i + ". " + snapshot.child("0/A_Inside_Bus " + i).val();
document.getElementById('A_Inside_Bus_' + (i+1) + '_Comments_div').innerText = snapshot.child("0/A_Inside_Bus " + i + " Comments").val();
}
Don't do this. Trying to make variable names to do what you're trying to do just leads to needlessly messy code down the road.
Stick all your elements into arrays:
var elems = [
A_Inside_Bus_1_div
A_Inside_Bus_2_div
...
];
var comments = [
A_Inside_Bus_1_Comments_div
A_Inside_Bus_2_Comments_div
...
];
Then just index the arrays:
for (var i = 0; i <= 4; i++) {
elems[i].innerText = i + ". " + snapshot.child("0/A_Inside_Bus " + i).val();
comments[i].innerText = snapshot.child("0/A_Inside_Bus " + i + " Comments").val();
}
This is an example of how you could do it with your current setup. Note though, it could be cleaned up. If each element of the elems array always has a partner in comments, it would make more sense to group them together in an object, and only have 1 array.
Also note that populating the arrays in a loop makes more sense. I just hardcoded the arrays here for the sake of brevity. I'm not sure how you're creating the elements originally. They should probably be created and put straight into the array instead of naming them and adding them later.
There are a couple ways you could go about doing this, but they tend to involve some pretty bad habits, like using eval or attaching variables to the global object so you can access them with a string:
var a = 1;
window['a']; //1
But there are better alternatives, the most common is probably storing them in equal-length arrays:
var divs = [div1, div2, div3];
var items = ['cat', 'dog', 'fish'];
items.forEach(function(element, index){
divs[index].innerText = items[i];
});
You could also look at building out a single array of objects:
var objects = [{div: div1, item: 'cat'}, {div: div2, item: 'dog'}, {div: div3, item: 'fish'}];
for object in objects {
object.div.innerText = object.item;
}

How to iterate through an array containing objects - javascript

I have an array containing objects that looks like this:
[{\"user\":\"mcnewsmcfc\",\"num\":11},{\"user\":\"ManCityFNH\",\"num\":7}];
I am then using:
var jsonu = JSON.parse(tweets.replace(/"/g, '\"'));
to remove all the unwanted characters from the array. My question is then how to iterate through the array and (EDIT) use the values of "user" and "num" for each object in the table (EDIT).
This is what I initally have but this does not extract the correct values:
for (var u in jsonu) {
var row = $('<row></row>');
row.append('<th>' + jsonu[u][0] + '</th><td>' + jsonu[u][1] + '</td>');
$('#userTable').append(row);
}
var tweets = '[{\"user\":\"mcnewsmcfc\",\"num\":11},{\"user\":\"ManCityFNH\",\"num\":7}]';
var jsonu = JSON.parse(tweets.replace(/"/g, '\"'));
for (var u in jsonu) {
var row = $('<row></row>');
row.append('<th>' + jsonu[u].user + '</th><td>' + jsonu[u].num + '</td>');
$('#userTable').append(row);
}
since jsonu is an array, u is just the index in the array. jsonu[u] will return back the object at that index in the array, which is a javascript object.
So to access the user and num property, simply call jsonu[u].user and jsonu[u].num

for in, how to limit the output?

For my Javascript course I got this code:
for (var i in window.navigator)
{
document.getElementById('divResult').innerHTML +=
i + ': ' + window.navigator[i] + '<br />';
}
</script>
The teacher (online) wants me to limit the results into maximal 10.
For me this is a big puzzle. From other questions about the for..in I think to know it is a discussable statement. But how to approach this for..in? As an array with i.length?
Just set a counter. In each iteration you increase the counter and when the counter reaches 10 you simply break out of your loop
Code:
// Since we're going to access this div multiple times it's best to
// store it outside of the for loop.
var output = document.getElementById('divResult');
var counter = 0;
for (var elem in window.navigator) {
var value = window.navigator[elem];
output.innerHTML += counter + ': ' + elem + '=' + value + '<br />';
++counter;
if (counter == 10) {
break;
}
}
Since you're new to JavaScript I would like to explain a little bit about for-in
If you want to get a specific value from an array you access it's element by index. So for example:
var myArray = [7, 5, 6, 6];
for (var i = 0; i < myArray.length; ++i) {
var value = myArray[i];
}
But now you want to loop through window.navigator and this element is not an array but a object. And since a object is key-value it does not have a index. So how do you loop through it?
Let's imagine window.navigator looks like this:
var navigator = {
myBrowser: 'Google Chrome',
myOtherProperty: 'otherValue',
AnotherProperty: 'anotherValue'
};
If we want to get the first element from our object we use
navigator.myBrowser
or
navigator['myBrowser'];
Now we want to loop through all the elements in our object. Since the normal for loop uses a index and objects don't have indexes we use the for in loop. This loop iterates through all the properties of our object and gives us the key.
for (var key in navigator) {
// Here we access a property in our object by the key given by our for loop.
var value = navigator[key];
}
So the first iteration our key is myBrowser and the value is Google Chrome
The next iteration the key is myOtherProperty and the value otherValue.
It is usually a good idea to use hasOwnProperty if you're looping through an object:
for (var key in navigator) {
if (navigator.hasOwnProperty(key) {
var value = navigator[key];
}
}
Hope this helps
The teacher came back with an answer for my for..in array problem:
<script>
var navigatorArray = [];
for (var i in window.navigator) {
navigatorArray.push(window.navigator[i]);
}
navigatorArray.sort();
console.log(navigatorArray);
var htmlString = '';
for (var j = 0; j < navigatorArray.length; j++) {
htmlString += navigatorArray[j] + '<br />';
}
with the .push habbit it should be possible to collect them in an array and index them.

How to most efficiently generate string from array of objects in javascript?

I have the following:
var students = [{name:"Jordan", age:"6"},{name:"Jake", age:"7"},{name:"Mark", age:"10"}]
I want to generate a string like this:
"Jordan,6|Jake,7|Mark,10"
What is the most efficient way to do this?
I am currently using:
var studentstr = "";
for(var i = 0; i < students.length; i++) {
studentstr = students['name'] + "," + students['age'] + "|"
}
studentstr = studentstr.substring(0, studentstr.length - 1);
Also, performance-wise, if I had an array of 2,000 items, is it "costly" to perform this transformation? The resulting string contains both keys in the object and not a single join on one object in the property.
You can map each student object to a string and then join them all with |:
var studentstr = students.map(function (student) {
return student.name + ',' + student.age;
}).join('|');
Also, performance-wise, if I had an array of 2,000 items, is it "costly" to perform this transformation?
No.
Yes, using string concatenation in a loop is costly. The string grows for each iteration, and each time you have to copy the entire previous string to create the new version. The execution time of the loop grows exponentially to the number of items.
You can put the string for each object in an array, then join them together:
var students = [{name:"Jordan", age:"6"},{name:"Jake", age:"7"},{name:"Mark", age:"10"}];
var items = [];
for (var i = 0; i < students.length; i++) {
items.push(students[i].name + ',' +students[i].age);
}
var str = items.join('|');
// display result in snippet
document.write(str);
map works well for this:
var students = [{name:"Jordan", age:"6"},{name:"Jake", age:"7"},{name:"Mark", age:"10"}];
var result = students.map(function(student) {
return student.name + ',' + student.age;
});
alert(result.join('|'));
Try this and see your console:
var string = '';
for (var s in students) {
string += students[s].name + ', ' + students[s].age + ' | ';
}
console.log(string);
Fiddle: http://jsfiddle.net/80ss0u14/
I do not think it is costly to go on with such approach. It may be the most efficient way to iterate through the data.

How to create an array of variables from an array in Javascript

I have a variable called "information" which creates a multi-dimensional array. For each row in the array, I want to return a variable whose name is the first value in the array. In other words, given the 'information' array below, I'd want the following output:
var lunalovegood = information[i][2] + ' ' + information[i][3] + ' is a ' + information[i] [1] + '!'; //Luna Lovegood is a Ravenclaw!;
var dracomalfoy = information[i][2] + ' ' + information[i][3] + ' is a ' + information[i] [1] + '!'; //Draco Malfoy is a Slythering!;;
var hermionegranger = information[i][2] + ' ' + information[i][3] + ' is a ' + information[i] [1] + '!'; //Hermione Granger is a Gryffindor!;;
In other words, I want to be able to work with each of the elements in the 'information' array to create some markup. I already know how to get the information I need given the information array, but as you can see below I'd have to declare separate variables for each of the names.
for (var i = 0; i < information.length; i++) {
var htmlString = information[i][2] + ' ' + information[i][3] + ' is a ' + information[i] [1] + '!'; //Luna Lovegood is a Ravenclaw!
$('div').html(htmlString);
} //end for loop
var information = [
['lunalovegood', 'Ravenclaw', 'Luna', 'Lovegood', '(chaser)', 'lovegood.jpg', 4]
['dracomalfoy', 'Slytherin', 'Draco', 'Malfoy', '(seeker)', 'malfoy.jpg', 2],
['hermionegranger', 'Gryffindor', 'Hermione', 'Granger', '(none)', 'granger.jpg', 3],
];
The javascript below creates three variables called 'lunalovegood', 'dracomalfoy', and 'hermionegrange', but it's the long way of creating variables. How do I create these variables, one for each row in the array, by looping through the 0th indexed element in the 'information' array?
var myVariables = {}
,varNames = ["lunalovegood","dracomalfoy","hermionegranger"];
for (var i=0;i<varNames.length;i+=1){
myVariables[varNames[i]] = 0;
console.log(lunalovegood);
}
Your current approach just needs a most minor tweak to not require the second array.
var students = {}, i;
for (i = 0; i < information.length; ++i)
students[information[i][0]] = information[i][2] + ' ' + information[i][3] + ' is a ' + information[i][1] + '!';
Now the key is set by taking the first item of the Array. You would then do the following for your text,
students['lunalovegood']; // "Luna Lovegood is a Ravenclaw!"
You're also missing a , in your information literal.
This should help you:
Every variable in the global scope can be accessed as a string property of the window object
var myvariable = 4;
alert(window["myvariable"]); // will alert 4
window["newvariable"] = 6;
alert(newvariable); // will alert 6
I agree with Bergi. Variables should represent a fixed finite set of members defined by code; data (as in the contents of a list) should generally not introduce new variables.
As such, here is the approach I would recommend (note that I've added a bit more than the "minimum required"; good luck!):
// Using a function makes it easy to change details and avoid leaking
// variables accidentally.
function loadWizards(information) {
var wizards = [];
for (var i = 0; i < information.length; i++) {
var info = information[i];
var name = info[0];
// Mapping to named properties means we can forget about indices!
wizards[name] = { // <- use Name to map to our Wizard object
house: info[1],
// ..
image: info[7]
};
}
return wizards;
}
// I have no idea if they are wizards, but give variables useful names.
// 'information' is too generic.
var wizards = loadWizards(information);
// Then later on, use it as:
alert("Hello " + wizards['hermionegranger'].name + "!")
// ^-- property access by Name
var formattedInfo = {};
$.each(information, function (i, v) {
formattedInfo[v[0]] = v[2] + ' ' + v[3] + ' is a ' + v[1];
});
there is a missing comma at the end of the 1st line of your definition of information.
BTW, I like Harry Potter very much.

Categories

Resources