Please help me understand the logic in this 'for loop' - javascript

I am currently on Code Academy having fun learning. They have introduced push. and nested for loops pretty quickly without a lot of initial info. I THINK I understand the logic somewhat and would like to see if someone can help break it down...
var text = "Here is a string with the name rick sometimes not always rick and sometimes rick";
//assigning text string to variable text
var myName = "rick";
//assigning rick to variable myName
var hits = [];
// assinging an empty array to variable hits
for (var i = 0; i < text.length; i++); {
//for loop i = 0, and as long as i = less than the length of entire text string keep incrementing 1
if (text[i] === "r") {
//while looping through text when you find an "r" enter second for loop
for(var j = i; j < (i+ myName.length); j++){
//J takes the value of i at this point and it should be 0 and should increment 4 steps as myName = 4 characters
hits.push(text[j]);
//this push statement should add each letter of my name to the hits array
}
}
}
At this time my code does not work. I placed a console.log under the first for loop and it just prints 84.
"console.log("I= " +I)"
I understand this is pretty n00b but I really want to follow the logic and understand what is happening. Am I close?

You are really close.
You just have one problem:
The ";" after the for. It just goes to the end of the "for" loop doing nothing.
Take it out and it will work!!
Another thing you may like is to add to the list "hits" all the word that follows the 'r' character.
You should do:
if (text[i] === "r") {
var word = "";
for(var j = i; j < (i+ myName.length); j++) {
word+=text[j];
}
hits.push(word);
}
Also, be careful that i+myName.length is still in the limit of text.length (that is, i+myName.length < text.length)
Hope it helps!

Your code is pretty close. You accidentally put a semicolon after your first for loop:
for (var i = 0; i < text.length; i++);
This basically makes a 1 line block, same as this:
for (var i = 0; i < text.length; i++) {
}
Take that semicolon out and it should do what you want : ). although if your intent is to only push the ricks in then you need to check for more than just "r" you need to validate that each character after is also equal to rick.

You have a ";" after the for that should not be there. Also, you are still limited by the length of you string. So, you for statement becomes:
for(var j = i; j < (i + myName.length) && i < text.length; j++){
For example, if you had a string that was 82 characters long and you found an 'r' at the end of your text (i = 81), your original loop would set j to 81 and then try to check for characters in your string for indexes 82, 83, 84, and 85 which do not exist and would cause an error. Adding the addition check of i < text.length makes sure you do not try to check items that don't exists.
I don't know how far you are in your course. Just in case, the '&&' is an AND so j has to be less than (i + myName.length) AND also less than text.length.
Here is a JSFiddle of it working (http://jsfiddle.net/onlinespaces/xj39974c/1/)
Using JSFiddle is a great tool for things like this.
Good luck!

Related

Break and Continues

I wonder if someone can clarify something for me. I have a bit of code to check an array for overlapping values depending on different values. Basically its the contents of a google sheet in rows and comumns for this is specifically GAS. What I have at the moment is
var e = [[2,4,3,4,2],[1,5,3,6,2],[2,4,3,4,1],[1,4,3,6,1],[2,4,3,6,5]];
var i; //id of entry to check
var j; //id of element to check
var k; //id of entry to compare
for (i in e){ //2D ARRAY ARRAY
for (k in e){ //ELEMENT TO COMPARE
if (e[i][2] === e[k][2] && e[i][3] === e[k][3] && e[i][0] && e[i][0] >= e[k][0] && e[i][1] <= e[k][1] && e[i][4] <= e[k][4] && i !=k){
e.splice(i,1);
continue;
}
}
}
return e;
I had to add the continue; as otherwise if the last array checked was also marked for splice the code failed. But I assumed break would also work in place of continue but for some reason it does not. I thought break would return to the outside loop but does it permanently break that bit of code?
Thanks people
EDIT: spoke too soon. code still fails even with continue. head scratching continues
continue jumps directly to the next iteration, so:
while(true) {
console.log("a");
continue;
console.log("b");
}
will only log a as it will jump back to the beginnig of the loop if it reaches continue.If you however move continue to the last line of the loop (just as in your code) it does nothing as it would jump to the begining to the loop one line later, so it just skips an empty line.
I thought break would return to the outside loop
Yup, thats what happens and that is actually a good thing as if you removed the element already, it won't make sense to check for other dupes as you don't want to remove it twice.
Now the real problem is that splice changes the indexes, so if you splice out the fourth element, the fith element becomes the fourth element, but the loop continues to the fith element without checking the fourth element again (which is now a different one). Therefore you have to go back by one element before you break:
for(let i = 0; i < e.length; i++) {
for(let k = 0; k < e.length; k++) {
if(i === k) continue; // < good usecase
if(/* equality checks */) {
e.splice(i, 1); // remove the element
i--; // go back by one as we changed the order
break; // exit the inner loop
}
}
}
IMO:
1) I would favor for(const [i, value] of arr.entries() over for..in
2) you will forget what arr[i][2] is very soon, giving proper names to the indexes makes it way more readable:
const [idA, someValueA] = e[i];
const [idB, someValueB] = e[k];
if(idA === idB && someValueA <= someValueB // ...
3) e is a bad name.
You can use a labelled break to break out of nested loops.
eg
var num = 0;
outermost:
for(var i = 0; i < 10; i++){
for(var j = 0; j < 10 ; j++){
if(i == 5 && j == 5){
break outermost;
}
num++;
}
}

Nested Javascript for loops with break and label statements

I'm kinda new to Javascript and currently going over the book Professional Javascript for Web Developers and I came across this code which uses a break statement to exit the current loop and jump to a label named outermost.
Now I understand what break and labels do but I can't wrap my head around why the value ends up being 55 at the end?
Ok so the for loop with var i will loop 4 times then at 5 it breaks out to label:outermost and same with j so the first iteration i = 4 and j = 4 and num = 2. I guess this part confuses me.. at what point does the code stop. My first instinct if I were to code this from scratch is to have an outside variable and set the condition on that. But with the below code I don't get where the control structure lies and the final value. Appreciate any help or to be pointed in the right direction, thanks.
var num = 0;
outermost:
for (var i=0; i < 10; i++) {
for (var j=0; j < 10; j++) {
if (i == 5 && j == 5) {
break outermost;
}
num++;
}
}
alert(num);
This nested loop is emulating an odometer. i is the 10's digit, j is the 1's digit. Every time the 1's digit changes, num is incremented; at the start of each iteration, num contains the odometer's value.
The loop stops when both i and j are 5. At that point, the odometer would read 55, and that's what is in num.
When i was 0 to 4, the innermost loop is executed 50 times. When i = 5, the innermost loop is executed just 5 times until it reached i==5 && j==5 and jumped out. So it's total of 55 times.

javascript issue undefined variable in array

Can someone please tell me what's wrong with this code? Chrome and Firefox are saying that scrns[i] is undefined though Chrome still runs the code on mouseover.
function nextPrev() {
if (!document.getElementsByClassName) return false;
var scrns = document.getElementsByClassName('scrn');
for (var i=0; i<=scrns.length; i++) {
// console.log(i);
scrns[i].onmouseover = function() {
// console.log('foo');
}
}
}
window.onload = nextPrev();
I've tested that the for loop is working and tried to pin down where the problem is coming from in every way I know how. I'm even looking at an example I took from a book sometime ago and cannot understand why scrns[i] would be undefined.
Any help greatly appreciated!
You're using <= when looping through. But remember that arrays are indexed starting at 0, not 1. So an array with 10 elements has a length of 10, but elements 0-9. Change the following:
for (var i=0; i<=scrns.length; i++) {
to:
for (var i=0; i < scrns.length; i++) {
You are looping too far. If i is equal to scrns.length then it is beyond the end of the array. Remove the = in your stop condition:
for (var i=0; i < scrns.length; i++) {
You have an off by one error. Changing <= to < should fix your issue. You can use loop invariants in the future to make sure that you don't go over.
http://en.wikipedia.org/wiki/Loop_invariant
In general though, when looping through an array, begin with the iterating counter at 0 and then loop so long as the counter is less than the length of the array.

javascript array for loop i+1 returning undefined

array ref.length = 7 (0 - 6), and I want to try to match ref[0]['x'] to ref[1]['x'] I am doing this:
for(var i=0;i<ref.length;i++){
if( ref[i]['x'] != ref[i+1]['x'] && ref[i+1]['x'].length > 0 )
//do something
}
The for loop is iterating all the way to array number 6 then element 6+1 is blank so I get an error on the if statement line saying ref[i+1] is undefined....
is there a better way to do this?
Better:
for (var i=ref.length-2;i>=0;i--)
Javascript will evaluate the condition on each iteration, so it's generally preferable go backwards instead. With this construct "ref.length" is only evaluated once. Another alternative I like which will perform the same:
var i=ref.length-1;
while (i--) {
}
(Normally you'd be i=ref.length-1 in the first example, and i=ref.length in the second, but you're trying to stay one less than the array length).
for (var i=0; i<ref.length-1; i++) { // Note the "-1".
This way when you use the index i+1 you're still in bounds.
for (var i = 0; i < ref.length - 1; i++)
What about:
for(var i=0;i<ref.length-1;i++){
If you just use ref.length-1 won't that solve your problem? I might not fully understand what you're asking.
Here's a simple solution.
Just count the counter again.
if( ref[i]['x'] != ref[++i]['x'] && ref[++i]['x'].length > 0 )

Problem with using javascript to insert <input> tags in html

I am trying to take text that is in an array (one word per value) and insert it into html. All the code is here: http://jsfiddle.net/chromedude/r6wVq/3/.
Update:
My question is what am I doing wrong? It does not do anything which is weird.
Just for everybody who was wondering what this code is supposed to help me do is memorize long passages for school.
You have an infinite loop, that's why the browser crashes:
for (i = 0; i < text.length; i++) {
var currentText = text[i];
for (i = 0; i<blanks.length; i++){}
}
The second loop always resets the counter variable i to 0. If you have nested loops you have to use different variables. And use var to declare the variables as local, e.g.
for (var i = 0; i < text.length; i++) {
var currentText = text[i];
for ( var j = 0; j<blanks.length; j++){
}
}
Same for your most outer for loop!
I don't know exactly what you want to achieve with the code, but here are some comments:
var blankNum = Math.random(Math.floor() * (text.length / 2));
Math.random takes no parameter, but Math.floor does.
for (i = 0; i < blanks.length; i++) {
blanks is still empty at this point, so the loop will never run.
if (currentText==blanks[i]){
Are you sure that blanks[i] will contain text? The previous mentioned (never running) loop seems to add numbers to the array.
textPrelim = <input type="text"></input>
You get a syntax error here, you must enclose the string into quotes.
I fixed your fiddle: http://jsfiddle.net/yEKPt/1/
What was wrong:
for iterator scope (here)
This line (27) threw a syntax error:
textPrelim = <input type="text"></input> //Needs to be quoted.
Should be:
textPrelim = '<input type="text"></input>'; //Quoted.
You reversed Math.random and Math.floor (lines 8, 14). (See: Math.Random(), Math.Floor())
var blank = Math.random(Math.floor() * (text.length / 2));
Check out my revised version. I think it accomplishes what you were looking for?
With addition to Felix's answer, try to check your code at http://www.jslint.com for syntax errors and undeclared (implicitly global) variables.

Categories

Resources