Javascript If Statement not Evaluating True - javascript

I am attempting to catch the last case in a forEach loop, but all cases seem to evaluate to false instead of the last one being true. My code:
for(var i in networks){
if (i == (networks.length - 1)){
//do stuff
}
}
What is going wrong?

Try this:
for(var i = 0, j = networks.length; i < j; i++){
if (i == (j - 1)){
//do stuff
}
}
I personally despise the for...in loop in JavaScript because it brings into the picture a whole bunch of unwanted properties, it's unreliable - needs a ton of sanity checks to make sure the current property is not of an unwanted type or undefined. I can go on and on about this. I suggest that the only time that you ever think of using it is when you are iterating over objects and you need key values.

If networks is an array of numbers in order from 0 to n, that should work. ;) If it's not, you might want to consider a standard for loop:
for(var i = 0; i < networks.length; i++) {
var network = networks[i]; // in case you need this.
if (i == (networks.length - 1)){
//do stuff
}
}

Related

Explanation How Rectangle Recursion JavaScript works

I am a beginner in code world. I have troubles understanding recursion in JavaScript especially when it needs two or more looping. Like I want to print rectangle using recursion. I don't know completely how to make a base case, condition when it still executed. For examples, these codes below I use to print rectangle or holey rectangle.
function box(num) {
for (let i = 0; i < num; i++) {
let str = ''
for (let j = 0; j < num; j++) {
str += '*'
}
console.log(str)
}
}
box(5)
function holeBox (num) {
for(let i = 0; i < num; i++){
let str = ''
for(let j = 0; j < num; j++){
if(i == 0 || i == num -1 || j == 0 || j == num - 1) {
str += '*'
} else {
str += ' '
}
}
console.log(str)
}
}
holeBox (5)
Please help me to understand recursion, an explanation would be great. My goals are not only to solve those codes but also to understand how recursion works. I've searched there's no good source to learn recursion, or I just too dumb to understand. Thanks in advance
To understand how recursion works, just think of how you can split up what you want to accomplish into smaller tasks, and how the function can complete one of those tasks, and then call itself to do the next- and so on until it is finished. I personally don't think printing boxes is the best way to learn recursion, so imagine you wanted to search an array for a specific value; ignore JavaScript's indexOf()/find() functions or similar for now.
To do this using loops, its easy, just iterate over the array, and check every value:
//Returns the index of the first occurrence of a value in an array, or -1 if nothing is found
function search(needle, haystack) {
for (let i = 0; i < haystack.length; i++) {
if (haystack[i] == needle) return i;
}
return -1;
}
Doing this using recursion is easy as well:
function recursiveSearch(needle, haystack, i) {
if (i > (haystack.length - 1)) return -1; //check if we are at the end of the array
if (haystack[i] == needle) return i; //check if we've found what we're looking for
//if we haven't found the value yet and we're not at the end of the array, call this function to look at the next element
return recursiveSearch(needle, haystack, i + 1);
}
These functions do the same thing, just differently. In the recursive function, the two if statements are the base cases. The function:
Tests if the current element is out of bounds of the array (meaning we've already searched every element), and if so, returns -1
Tests if the current element is what we're looking for, and if so, returns the index
If neither of the statements above apply, we call this function recursively to check the next element
Repeat this until one of the base cases kicks in.
Note that recursive functions are usually called from other helper functions so that you don't have to pass the initial parameters to call the function. For example, the recursiveSearch() function above would be private, and it would be called by another function like this:
function search(needle, haystack) {
return recursiveSearch(needle, haystack, 0);
}
so that we don't have to include the third parameter when we call it, thus decreasing confusion.
Yes, even your box code can be turn into recursion but I don't think it will help you understand the concept of recursion.
If you really have to:
function getBox(arr, size) {
let length = arr.length;
if (length == size)
return arr; // recursion stop rule - if the size reached
for (let i = 0; i < length; i++)
arr[i].push("*"); // fill new size for all row
arr.push(new Array(length + 1).fill("*")); // add new row
return getBox(arr, size); // recursive call with arr bigger in 1 row
}
However, I believe #Gumbo answer explain the concept better then this...

What is the point of using empty statement in JavaScript?

I tried to search for good resources on empty statement, but it seem like nothing show up. Even on MDN, they don't have much to say about it.
i.e:
for(var i = 0; i < a.length; a[i++] = 0);
if((a==0) || (b == 0));
I would like to know what are some real examples that one should use empty statements on their project. What are the reason behind it?
The examples you've given don't make much sense. They should better be written
for (var i = 0; i < a.length;) a[i++] = 0;
for (var i = 0; i < a.length; i++) a[i] = 0;
; // the comparisons really don't do anything (assuming a and b are no objects)
(a==0) || (b = 0); // Oh wait, that's the one given by #Shomz
if (a != 0) b = 0;
However, there are real-world applications for the empty statement. I'll just list 3 that come to my mind:
function x() {
…
};
A semicolon where it doesn't belong (e.g. after the function declaration above) makes an empty statement.
;
…
A leading semicolon on your script files helps to guard against buggy inclusions or file concatenations.
while (!check_for_finish()); // do nothing
An empty loop body can be used for busy-waiting loops (not recommended) and similar.
none/lazyness. there is absolutely no difference to
for(var i = 0; i < a.length;) a[i++] = 0;
and just a minimal difference to
for(var i = 0; i < a.length; i++) a[i] = 0;
the first one is a few ms faster after a few billion iteration steps; aka. premature optimization
EDIT:
if((a==0) || (b == 0));
this makes no sense at all, since it does nothing.
but expresions like
a==0 || (b=0);
//or maybe sth like this:
//var noop = ()=>void 0; //FYI
typeof a === "function" || (a = noop);
are pretty useful to me, since they are short, and readable and an additional if-statement doesn't add any value to readability or understanding (at least once you know this pattern).
The first one obviously loops through the array and assigns all values to zero, without having the code specified in the statement.
The other one seems like a typo, because it is useless.
However, something like
if((a==0) || (b = 0));
would make sense, as it would assign b to zero in case a is not zero.
var a = 1, b = 1;
if((a == 0) || (b = 0));
alert("a: " + a + ", b: " + b);
I do not think that they are really useful, but I can be wrong.
One can try to use side effects of the evaluation of the conditions in an if, but I do not see a good reason to do so.
My favorite use for it is to wait for a condition to become true.
while ( !condition );
// do what happens once your condition is met
This is nice to read, in my opinion, but the same can be done with { } instead of the empty statement.
The first example for(var i = 0; i < a.length; a[i++] = 0); is useful IMO, and the reasons would be:
Writing less without sacrificing readability.
beauty!
Telling people: Hey, I'm a pro JS coder. :)
The second one if((a==0) || (b == 0)); seems doesn't nothing.
Let us suppose you have two functions X and Y and let us suppose that Y must only be executed when X returns true, in such a situation you will write:
if( X() && Y() );

Prevent javascript from going out of an array

Is there any way I can prevent javascript from dropping an error if I try to go into a non existing array index?
Example: array[-1] would return error and eventually break all my code. How can I let it just return 'undefined' and let my script go on? I can implement an if statement before checking the array (so that if the index is minor than zero or major than the array size it would skip it) but this would be very tedious!
this is my code:
if (grid[j-1][i])
n++;
if (grid[j+1][i])
n++;
if (grid[j][i+1])
n++;
if (grid[j][i-1])
n++;
if (grid[j-1][i-1])
n++;
if (grid[j+1][i+1])
n++;
if (grid[j-1][i+1])
n++;
if (grid[j+1][i-1])
n++;
It is inside of two loops which both sees J and I starting from zero. I don't want to change them and neither writing another if statement (as you can see, there are already too much of them!). Is there any solution?
Thanks!
If you know the measures of your grid, you can put "sentinel cells" around it.
If you add a -1st index to an array x, it does not count to x.length. Putting an additional last element into the list would increment x.length.
I daresay using sentinel cells combined with the arithmetic counting algorithms mentioned by d_inevitable would be the fastest solution, since it would not involve branches. You even can omit the !! because true will evaluate to 1 and false to 0 in an equalization.
Update:
Do not use index -1. Its an awful lot slower that normal array indexes. See http://jsperf.com/index-1.
You could use ||, which muffles errors, e.g.:
(grid[j-1] || [])[i] || false
(I haven't tested this, but it should work)
Edit: updated based on am not i am's suggestion
A less tedious way while still using ifs would be checking the first index if it's defined:
if (typeof grid[j-1] != "undefined" && grid[j-1][i])
You could create a function to do the checks:
function getArrayValue(arr,key) {
if( key < 0 || key >= arr.length) return null;
return arr[key];
}
But really you should be avoiding out-of-bounds keys anyway.
I would do this:
for(m = Math.max(j-1,0) ; m <= Math.min(j+1,grid.length-1) ; m++)
for (p = Math.max(i-1,0) ; p <= Math.min(i+1, grid[m].length-1) ; p++)
n += !(m == j && p == i) && !!grid[m][p];
How about this for your solution?
for (dj = -1; dj <= 1; ++dj) {
for (di = -1; di <= 1; ++di) {
if ((dj || di) && grid[j+dj] && grid[j+dj][i+di]) {
n++;
}
}
}
If you refactor all those ifs into a single loop like the above, then having to do the extra conditional is not so bad.

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 )

Why is my nested for loop not working as I expected?

I have trouble dealing with my for loops now, I'm trying to compare two datum, basically it will compare 2 items, then it will write the matches and the mismatches on the webpage.
I managed to write the matches on the webpage, it was working good. But there's a bug in my mismatch compare.
It wrote all the data on the webpage X times, here's my JS code:
function testItems(i1, i2) {
var newArray = [];
var newArray2 = [];
var count = 0;
var count2 = 0;
for(var i = 0; i < i1.length; i++) {
for(var j = 0; j < i2.length; j++) {
if(i1[i] == i2[j]) {
newArray.push(i1[i]);
count++;
} if (i1[i] !== i2[j]) {
newArray2.push(i1[i]);
count2++;
}
}
}
count-=2;
count2-=2
writeHTML(count,count2, newArray, newArray2);
}
The result was horrible for the mismatches:
alt text http://www.picamatic.com/show/2009/03/01/07/44/2523028_672x48.jpg
I was expecting it to show the mistakes, not all the strings.
The issue you're seeing is because of the nested for loop. You are essentially doing a cross-compare: for every item in i1, you are comparing it to every item in i2 (remember that j starts again at 0 every time i advances... the two loops don't run in parallel).
Since I understand from the comments below that you want to be able to compare one array to the other, even if the items in each are in a different order, I've edited my original suggestion. Note that the snippet below does not normalize differences in case between the two arrays... don't know if that's a concern. Also note that it only compares i1 against i2... not both i1 to i2 and i2 to i1, which would make the task a little more challenging.
function testItems(i1, i2) {
var newArray = [];
var newArray2 = [];
for (var i = 0; i < i1.length; i++) {
var found = false;
for (var j = 0; j < i2.length; j++) {
if (i1[i] == i2[j]) found = true;
}
if (found) {
newArray.push(i1[i])
} else {
newArray2.push(i1[i])
}
}
}
As an alternative, you could consider using a hash table to index i1/i2, but since the example of strings in your comment include spaces and I don't know if you're using any javascript helper libraries, it's probably best to stick with the nested for loops. The snippet also makes no attempt to weed out duplicates.
Another optimization you might consider is that your newArray and newArray2 arrays contain their own length property, so you don't need to pass the count to your HTML writer. When the writer receives the arrays, it can ask each one for the .length property to know how large each one is.
Not directly related to the question but you should see this:
Google techtalks about javascript
Maybe it will enlighten you :)
Couple of things about your question. First you should use '!=' instead of '!==' to check inequality. Second I am not sure why you are doing decreasing counts by 2, suggests to me that there may be duplicates in the array?! In any case your logic was wrong which was corrected by Jarrett later, but that was not a totally correct/complete answer either. Read ahead.
Your task sounds like "Given two set of arrays i1 & i2 to find i1 {intersection} i2 and i1{dash} {UNION} i2{dash}) (Group theory notation). i.e. You want to list common elements in newArray and uncommon elements in newArray2.
You need to do this.
1) Remove duplicates in both the arrays. (For improving the program efficiency later on) (This is not a MUST to get the desired result - you can skip it)
i1 = removeDuplicate(i1);
i2 = removeDuplicate(i2);
(Implementation for removeDuplicate not given).
2) Pass through i1 and find i1{dash} and i1 {intersection} i2.
var newArray = [];
var newArray2 = [];
for (var i = 0; i < i1.length; i++)
{
var found = false;
for (var j = 0; j < i2.length; j++)
{
if (i1[i] == i2[j])
{
found = true;
newArray.push(i1[i]); //add to i1 {intersection} i2.
count++;
break; //once found don't check the remaining items
}
}
if (!found)
{
newArray2.push(i1[i]); //add i1{dash} to i1{dash} {UNION} i2{dash}
count2++;[
}
}
3) Pass through i2 and append i2{dash} to i1{dash}
for(var x=0; x<i2.length; x++)
{
var found = false;
//check in intersection array as it'd be faster than checking through i1
for(var y=0; y<newArray.length; y++) {
if( i2[x] == newArray[y])
{
found = true;
break;
}
}
if(!found)
{
newArray2.push(i2[x]); //append(Union) a2{dash} to a1{dash}
count2++;
}
}
writeHTML(count,count2, newArray, newArray2);
I have a feeling that this has to do with your second comparison using "!==" instead of "!="
"!==" is the inverse of "===", not "==". !== is a more strict comparison which does not do any type casting.
For instance (5 != '5') is false, where as (5 !== '5') is true. This means it's possible that you could be pushing to both arrays in the nested loop, since if(i1[i] == i2[j]) and if(i1[i] !== i2[j]) could both be true at the same time.
The fundamental problem here is that a pair of nested loops is NOT the right approach.
You need to walk a pointer through each dataset. ONE loop that advances both as needed.
Note that figuring out which to advance in case of a mismatch is a much bigger problem than simply walking them through. Finding the first mismatch isn't a problem, getting back on track after finding it is quite difficult.

Categories

Resources