Short-Circuiting to Print Every Value - javascript

Here is my code:
for (let i = 0; i <= 100; i++) {
let output = "";
if (i % 3 === 0) {
output += "Cool";
}
if (i % 5 === 0) {
output += "Breeze";
}
console.log(output || i);
}
In this code, I use a for loop to vary the value of the binding i from 0 to 100.
In the first if statement, I use the modulo and the addition assignment operator to add the string "Cool" to the binding output.
In the second if statement, I use the modulo and the addition assignment operator to add the string "Breeze" to the binding output.
The function of my last statement in the body of my for loop is to print the value of the output binding in the browser console. I do this through short-circuiting. Now, I understand the logic of short-circuiting with the "OR" operator, since the interpreter will short-circuit its full logic of comparing both operands and automatically choose the operand on the left if it can be converted to true, which strings and numbers can, so the operand output is always going to be chosen.
What I don't understand is why short-circuiting is needed to visibly print every value in the console. If I were to use the statement console.log(output); it consolidates the number type values, stating how many were printed in a row before it had to print a string.
Can someone please explain this logic? Why is short-circuiting needed here to prevent the consolidation?

If I were to use the statement console.log(output); it consolidates the number type values, stating how many were printed in a row before it had to print a string.
In case it isn't clear to others, what you're referring to is this:
This is an artifact of the browser console, which consolidates duplicate logs together, to make debugging easier. Here, it's consolidating the duplicate logged empty strings. It's not a issue with your code's logic. If you were to log the output by any other method, the blank outputs would be displayed serially, as you'd expect, rather than being clumped together:
const table = document.querySelector('table').children[0];
for (let i = 0; i <= 100; i++) {
let output = "";
if (i % 3 === 0) {
output += "Cool";
}
if (i % 5 === 0) {
output += "Breeze";
}
table.innerHTML += `<tr>Cell value: ${output}</tr>`;
}
<table>
<tbody>
</tbody>
</table>
Your code is perfectly fine, you just need to find a way to display it other than console.log so that its unintuitive clumping doesn't mess things up.
You can also turn off the grouping by unchecking "Group Similar":

Related

Why isn't this function working like I expect it to? Trying to determine if a string has two repeating consecutive letters, like the o's in book

So here's what I have so far...
function doubleCheck(str){
for (var i = 0; i <= str.length; i++){
var n = i + 1;
if (str[i] === str[n]){
return "True";
}
}
}
I'm pretty new to Javascript. I googled around and I see there are better ways to solve this problem probably, but I can't figure out why this isn't working the way I think it should. If I pass a word without two consecutive letters like "train" this still returns true. Any help is appreciated.
Your problem is that you did i <= str.length. Arrays in javascript start from 0.
In the case of 'train', it would go up to 5, which is undefined.
It would compare undefined (array[5]) with undefined (array[6]), which is true.

Two strings print as same but don't pass equality test?

I have a google script that reads in two files and checks for equality between them. When I log the values checked they are the same but my code doesn't work.
for(var i = 1; i < partData.length; i++){
Logger.log("Part Data" + partData[1][2]);
Logger.log("Name" + name);
if(partData[1][2] === name)
{
temp = i + 1;
}
}
Log:
[18-07-13 06:56:15:876 PDT] Part DataES002-101
[18-07-13 06:56:15:877 PDT] NameES002-101
Why are "ES002-101" and "ES002-101" not equal?? They are from different sheets and the same font, although one is smaller and bold but that shouldn't matter right?
Try using the code as follows:
partData[1][2].toString().trim() == name.toString().trim()
If still doesn't work then try using the following:
partData[1][2].toString().replace(/ /g,'')==name.toString().replace(/ /g,'')
I have just tried converting the objects into the string and replaced all spaces to compare. But you should be careful using the above condition as this doesn't compare the real strings.

console.log("this.length--->" + this.length); this behaviour

I am trying to learn js basics.
I tried analysing the string count code but I am not sure about certain statements.
can you guys tell me why it's behaving in such a way?
this will help to understand better and in future, I can fix the issues by myself.
providing code below
String.prototype.count=function(c) {
var result = 0;
var i = 0;
console.log("this--->" + this); // how come this prints strings here, since we dont pass stings here
console.log("this.length--->" + this.length);
for(i;i<this.length;i++)
{
console.log("this[i]--->" + this[i]); // here we did not declare this an array anywhere right then how come its taking this[i] as s and stings also we did not put in any array
console.log("c--->" + c);
if(this[i]==c)
{
result++;
console.log("inside if result++ ---->" + result++);
// here it prints 1 and 3 but only two times s is present so it should print 1 and 2 right
}
}
console.log("out of for loop result--->" + result);
// how its printing 4 but s is present only two times
return result;
//console.log("out of for loop result--->" + result);
};
console.log("strings".count("s")); //2
output
this--->strings
this.length--->7
this[i]--->s
c--->s
inside if result++ ---->1
this[i]--->t
c--->s
this[i]--->r
c--->s
this[i]--->i
c--->s
this[i]--->n
c--->s
this[i]--->g
c--->s
this[i]--->s
c--->s
inside if result++ ---->3
out of for loop result--->4
4
Questions from your code example are basicly about 2 issues:
this - is JS keyword. You don't have to initialize it, it automatically defined everytime, everywhere in your JS code. And it could mean different things in different situations, but it's too advanced topic if you've just started learning JS. For now lets just say, that this refers to the context, that called count() function, which is the string "strings". So it has length and you can iterate over it as an array of characters
Why the count rose to number 4, when it should be 2? Because when you found a match between current letter of the string and the character "s" (line with this[i]==c) you increment the result by 1 using result++. But you do it also in your console.log right after it, so it gets increased by 2 every time it finds a match
console.log("this--->" + this); // how come this prints strings here, since we dont pass stings here
That prints a string because you have a string + something. This is called string concatenation and the result of string concatenation is a string. In this case, this is the object that called the count function which was a string.
console.log("this[i]--->" + this[i]); // here we did not declare this an array anywhere right then how come its taking this[i] as s and stings also we did not put in any array
this is a string. Bracket notation on a string will return the char at the provided index.
result++;
console.log("inside if result++ ---->" + result++);
// here it prints 1 and 3 but only two times s is present so it should print 1 and 2 right
the result++ notation is the same as result += 1, but result++ does the addition of 1 AFTER the value is evaluated while ++result will do it before. So in this example the order of events is:
add 1 to the result, then print the console.log, then add 1 to the result
Hope that helps!

If/then calculation within Zap running even when statement is false

Essentially what I'm attempting to do is circumvent when users enter a number in a non-standard format. For example:
1.5 million should be 1500000
Previous Zap step extracts the number using the Formatter > Extract Number function. So the result is the variable rawNum and the original number is noformatNum.
var str = inputData.noformatNum;
var n = inputData.noformatNum.includes ("million");
if (n = true) return {
finalNum: Number(inputData.rawNum) * 1000000
};
else return { finalNum : inputData.noformatNum };
It works in that it completes the operation and turns 1.5 to 1500000, but it executes each time, even if noformatNum doesn't include "million" in the string. I'm not super experienced with Javascript, but after digging around W3C and the Zapier documentation for a couple hours I'm stumped. Any help is much appreciated. Thanks!
It looks like there's a small but significant syntax issue here. You'll want to use a triple equal sign === instead of a single = in your conditional.
if (n = true) return {
should be
if (n === true) return {
In an if...else statement, the part in parenthesis (the "condition") should be something that evaluates to either a "truthy" or "falsy" value. (MDN)
n = true assigns the value of true to the variable n, so JavaScript considers the whole thing "truthy" no matter what.
n === true compares n to true, which is what you want for the if...else statement to work. The value will be "truthy" or "falsy" depending on the value of n.

Finding neighbors in a game of five-in-a-row

I can declare a winner if a player gets five of their tokens in a row, and now I am trying to implement the feature of capturing an opponent's pieces. For example, I am player X, I can trap O's pieces like this X00X in any direction on the board. In order to implement this, is the following logic correct:
Find all neighbors around O, check and see if the neighbor is an X or an O, if there are two 0's in a row surrounded by an X on each side, I can take those pieces. Is there a better way to approach this problem? I am thinking of something like this:
function isOCaptured(token, row, col){
if(gameBoard[row][col]==="O" && gameBoard[row][col+1] === "X"
&& gameBoard[row][col-1] === "X"){
return true;
}
return false;
}
But it does not seems to return true when I place one O in between two X's.
Here is what my server.js and app.js look like right now: https://jsfiddle.net/Amidi/s3gnx3rL/4/ The HTML is just a 13 x 13 grid of buttons with an event attached to each which sends the buttons coordinates to the add() function in my app.js
Now, the problem seems to be that the code only works if the "O" was placed last. This can be solved with a for-loop.
for(var i = -1; i <= 1; i++) {
if (gameBoard[row][col+i]==="O" && gameBoard[row][col+i+1] === "X"
&& gameBoard[row][col+i-1] === "X") {
return true;
}
}
return false;
You can also use a slice:
// The closest 5 cells to the left/right of the newly added piece, as a string
var str = gameBoard[row].slice(col-2,col+3).join("");
// Look for the pattern "XOX" in those 5 cells. Double negation to return bool.
return !!str.match("XOX");
Old answer
According to your comment, the code was called like this:
if(isOCaptured(x,y)===true){console.log("y is between 2 x\s");
This means that the function is called with two instead of three arguments. That will result in the following values of the arguments: token = x, row = y and col = undefined.
The expression being evaluated will thus be:
gameBoard[y][undefined]==="O" && gameBoard[y][undefined+1] === "X"
&& gameBoard[y][undefined-1] === "X"
Which would evaluate as follows:
Evaluating gameBoard[y] will succeed, resulting in a column (the wrong one though).
Then we try indexing the column with undefined, and since the array doesn't contain an element called undefined, it will fail, resulting in (again) undefined.
Then we compare this value undefined with "0", which is obviously false.
The expression false && ... will return false, as will the whole function.
If the second part would have been executed, it would calculate undefined+1, which is (quite accurately) evaluated to NaN (not a number). The array doesn't contain NaN either, so this calculation would evaluated to false as well.
Now, for some advice:
The statement if(expr){return true} else {return false} can be simplified to just return expr.
These kinds of bugs are pretty easy to find if you use the Chrome Debugger (or Firebug for firefox), where you can step through the code and see exactly what happens and where stuff goes wrong.

Categories