javascript issue undefined variable in array - javascript

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.

Related

JavaScript && JQuery : Iterating

I have managed to get so far but for some reason, it does not match the last number and run the else command I have in the code.
My current code is:
JavaScript Fiddle
If anyone could point me in the right direction it would be very much appreciated as I've spent the last 2 hours trying to figure this problem out and only managed to get this far.
The next and Previous works fine, along with the View more/less. Its the 'View next address' that the code seems to skip the else.
This code here is always skipped, my question is does anyone know why or can point me in the direction of fixing this?
else {
$(".activee").eq(idx).addClass("hidden");
$(".activee").eq(idx).removeClass("activee").prev().addClass("activee");
alert("Sorry, there is no more addresses to show...");
num[idx]--;
}
Thanks in advance!
Change your fiddle to this:
var num = []; // <-- changed to array from object
for (i = 0; i < leng; i++) { // <-- while i < leng
num.push(i);
}
Updated fiddle
for (i = 0; i == leng; i++) {
num.push(0);
}
you're pushing the value 0 to the num array
probably meant to do
for (i = 0; i == leng; i++) {
num.push(howMany[i]);
}
but I just skimmed the code, so am not sure whether the logic is even valid.

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

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!

for loop to print out multiple arrays with similar names

I've got multiple arrays, like so:
bugNames0 = ["wasp", "roach", "stinkbug", "mantis"];
bugNames1 = ["hornet", "beetle", "ant", "termite"];
bugNames2 = ["gnat", "fly", "grub", "chigger"];
bugNames3 = ["flea", "bed-bug","maggots", "cricket"];
Next up I have this for loop:
function bugLoop() {
for (var i=0; i < 4 ; i++){
console.log(bugNames0[i]);
}
}
That will successfully print the first array to console, or each individually if I manually update the number in the array's name.
But is there a way to do something more like this? This following code bit doesn't work, but I hope it explains what I am trying to do:
for (var i=0, j=0; i < 4; i++) {
console.log(bugNames(i)[j]);
}
}
Here i represents the bugName#, which I would like to get to update through 0 - 3 as the loop runs, printing out only the first option of each array represented by j.
Goal outcome printed to console would be:
"wasp", "hornet", "gnat", "flea"
Or something like that.
If possible I would like solutions only using vanilla JS as I'm working on a project (self assigned exercise) where I'm trying to complete it using vanilla. Kind of a force myself to get the know the language better exercise.
(Also, I've only been coding for 4 months, so sorry if this is a noob question. I couldn't find the answer online anywhere, just lots of loops on printing out arrays normally.)
If you can store your arrays within an array, that would be a better option.
For instance:
bugNames[0] = ["wasp", "roach", "stinkbug", "mantis"];
bugNames[1] = ["hornet", "beetle", "ant", "termite"];
bugNames[2] = ["gnat", "fly", "grub", "chigger"];
bugNames[3] = ["flea", "bed-bug","maggots", "cricket"];
Then you can loop through the bugNames array normally.
You could store all four arrays into one larger array (each bugNames array would simply be an element within this larger array). Let's call it bugCollection:
bugCollection = [["wasp", "roach", "stinkbug", "mantis"], ["hornet", "beetle", "ant", "termite"], ["gnat", "fly", "grub", "chigger"], ["flea", "bed-bug","maggots", "cricket"]]
Alternately, you could keep your variable storage of these arrays and say:
bugCollection = [bugNames0, bugNames1, bugNames2, bugNames3]
Then you could iterate through the larger array, logging out the index at each.
var oneFromEachArray = function(index) {
for (var i = 0; i < bugCollection.length; i++) {
console.log(bugCollection[i][index]);
}
}
oneFromEachArray(0) // Console logs 'wasp', 'hornet', 'gnat', 'flea'
You could try eval
for (var j=0; j < 4 ; j++){
for (var i=0; i < 4 ; i++){
eval("console.log(bugNames" + j + "[i]);");
}
}
You could use the function eval() like this:
for (var i=0, j=0; i < 4; i++) {
console.log(eval('bugNames' + i)[j]);
}
But did you already consider utilizing an array of arrays? Maybe that would be a cleaner way to achieve the same thing.
You can always access your variables using window object. Please use following code to access your variable dynamically.
for (var i=0, j=0; i < 4; i++) {
console.log(window["bugNames"+i][j]);
}

Need help with backtracking algorithm for generating Sudoku board

I have written an algorithm for generating a Sudoku board but it is failing. I have written it based on this though it does differ as I had written a lot of my code before I stumbled upon this.
The Code
I have a multidimensional array set up for holding the values called matrix. matrix consists of 9 arrays which are the rows and each of these hold the 9 columns. So to get the value at row 4 column 7 I would use
matrix[3][6];
The function for solving all the squares:
var populateMatrix = function() {
var possibles = generatePossibleNumbersArray();
var found = false;
for(var i=0; i< matrix.length; i++) {
for(var j=0; j< matrix[i].length; j++) {
while(possibles[i][j].length > 0) {
var rnd = Math.floor(Math.random() * possibles[i][j].length);
var num = possibles[i][j].splice(rnd, 1)[0];
if(isValid(i, j, num)) {
matrix[i][j] = num;
found = true;
break;
} else {
found = false;
continue;
}
}
if(!found) {
possibles[i][j] = [1,2,3,4,5,6,7,8,9];
j -= 2;
}
}
}
}
The generatePossibleNumbersArray() is just a helper function for creating a multidimensional array exactly like matrix except it is initialised to hold an array of integers 1-9 for each cell. During the populateMatrix() function these possible numbers get whittled down for each cell.
The Problem
It fails before completing the matrix every time because j ends up being -1. This is because as more cells get solved it becomes harder for the algorithm to find a value for a cell so it backtracks. But it eventually ends up backtracking all the way back until j == -1.
I really thought this algorithm would work and I've spent all day trying to get my head around this but I'm stumped so any light anyone could shed on this would be very much appreciated.
I thought 'I know, I'll write a javascript function for solving Sudoku. How hard can it be?'. How wrong I was.
[SOLUTION]
Based on a comment by #Steve314 (which he's now deleted!) I added matrix[i][j] = undefined into the if(!found) { ... and the algorithm now works and is lightening fast.
If anyone is interested, here is the complete code.
Backtracking algorithms usually restore the state if a branch fails and do the next possible move. So if the random filling of a field creates a failed branch just write back what was originally there.

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 )

Categories

Resources