Working my way through 'Eloquent Javascript' and I'm hitting a bit of a roadblock in understanding how to properly use if with for statements in the language. I'm supposed to write a function that counts all instances of the uppercase 'B' in a given string. The code I've written thus far:
function countBs(s) {
var counter = 0;
for (i = 0; i < s.length; i++) {
if ('B' == s.charAt(i)) {}
counter += 1;
}
}
console.log(countBs("BBC"));
expected output: 2
actual output: undefined
Is my loop going wrong, or my 'if'?
You have two bugs
You are incrementing your counter outside of the if statement.
You have no return statement.
The following can be used:
function countBs(s){
var counter = 0;
for(i = 0; i < s.length; i++){
if ('B' == s.charAt(i)) {
counter += 1; // this needs to be inside the if statement
}
}
return counter;
}
Your function does not have a return statement.
A few issues.
function countBs(s) {
var counter = 0;
for (i = 0; i < s.length; i++) {
if ('B' == s.charAt(i)) {
++counter;
}
}
return counter;
}
document.write(countBs("BBC"));
You were not returning counter at the end of the function
Your if statement was opened, then immediately closed, so nothing happens if the character was B
Even if you returned counter and fixed the above 2 errors, the function still would have exited after 1 B was found. To fix this, move the return after the for ends.
If you're interested, the same problem can be solved with this one-liner:
function countBs(s) {
return s.match(/B/g).length;
}
document.write(countBs("BBC"));
Which finds all B characters (case-sensitive), puts them into an array, then returns how many items are in that array.
Related
Here how it should work
const myArr =[6,8,10,5];
function weSort(arr){
let done = false;
while(!done){
done = true;
for(let i = 0; i < arr.length; i++){
if(arr[i]>arr[i+1]){
done = false;
[arr[i],arr[i+1]] = [arr[i+1],arr[i]]
}
}
}
return arr
}
console.log(weSort(myArr))
But if i change the i+1 to i++ it doesn't do anything because i++ is also 0.i++ is post increment which means it will increment right after it done executing (CMIIW)
const myArr =[6,8,10,5];
function weSort(arr){
let done = false;
while(!done){
done = true;
for(let i = 0; i < arr.length; i++){
if(arr[i]>arr[i++]){
done = false;
[arr[i],arr[i++]] = [arr[i++],arr[i]]
}
}
}
return arr
}
console.log(weSort(myArr))
But if i change the i++ to ++i shouldn't it work like the i+1 since ++i is pre-increment which will add first before got put inside [i]. So shouldn't it look like this?
let i = 0
arr[i]>arr[++i] === arr[0]>arr[1]
Like this code below (Note This Code cause infinite loop)
const myArr =[6,8,10,5];
function weSort(arr){
let done = false;
while(!done){
done = true;
for(let i = 0; i < arr.length; i++){
if(arr[i]>arr[++i]){
done = false;
[arr[i],arr[++i]] = [arr[++i],arr[i]]
}
}
}
return arr
}
console.log(weSort(myArr))
Why it works differently than the first code snippet with i+1?
and cause loop
if something not clear feel free to comment to ask for further info.
I'm sorry for the bad grammar English is not my native i try to explain the best i could.
Thank you.
i + 1 will do the calculation and return the result, leaving i untouched
i++ will return the value of i, then increment i (do i = i + 1)
++i will increment i (i = i + 1), then return its value.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#arithmetic_operators
The reason is that both i++ and ++i and are self assigning. Both the expressions modify the value of the variable i.
In your first snippet, the i + 1 does not modify the value of i - but only generates a new value by adding 1 to the current value of i.
No modification to the loop variable is done there - therefore the loop is not affected.
i++ (or ++i) should only be written one time. That increments the value. only do that once.
I think you want to avoid: arr[i]>arr[++i]
because now you are additionally incrementing i every time that check happens, which logically doesn't really make sense.
I have to create a function that checks if a word is palindrome or not. My reasoning is to break down the word letter by letter, normal and reverse, and then compare the two results to determine if a word is a palindrome or not. With an if - else I give the user an alert that tells perfectly the result. Now, I've learned that most of the functions must have a return with a variable that contains that desired result.
In this case I really can't have this, I think it can work perfectly this way. I tried with
var palindromeResult = (leftToRightWord == rightToLeftWord) ? 'true':'false';
console.log(palindromeResult);
return palindromeResult;
but it works only for the developer if he reads the console.log in the console, but it's a bad solution for me... Have you got any better idea than this? Below my full function code
function isPalindrome(wordToCheck) {
for(var i = 0; i < wordToCheck.length; i++) {
var leftToRightWord = wordToCheck[i];
console.log('Left ' + leftToRightWord);
}
for(var j = wordToCheck.length - 1; j >= 0; j--) {
var rightToLeftWord = wordToCheck[j];
console.log('Right ' + rightToLeftWord);
}
if ( leftToRightWord === rightToLeftWord) {
alert('La parola è palindroma');
} else {
alert('La parola non è palindroma');
}
Edit: At the end I changed a lot my code for a better legibility.
//Data
var userWord;
//I ask a word to the user
do {
userWord = prompt("Dimmi una parola");
} while (userWord.length === 0)
//Here the result of the function is saved and it can be reused
var functionResult = isPalindrome(userWord);
console.log (functionResult);
//Function to know if the word inserted is a palindrome or not
//the cycle with rightToLeft reverse the word so it can be compared to the normal word
//A pop-up will give the solution so it can be seen clearly on your screen
//The function result will ben saved outside the function in var functionResult so it can be seen with a console.log or reused for whatever use
function isPalindrome(wordToCheck) {
var rightToLeftWord = '';
for(var j = wordToCheck.length - 1; j >= 0; j--) {
rightToLeftWord = rightToLeftWord + wordToCheck[j];
}
console.log(rightToLeftWord);
var palindromeResult = wordToCheck == rightToLeftWord;
alert(palindromeResult);
return palindromeResult;
}
Now the cycle with for doesn't have problems anymore as you've pointed out to me and it correctly recognize if a word is a palindrome or not.
See the snippet. The function returns the answer and then you can alert it, assign it to a variable, echo it on the page and so on. I'm not pretty sure about your algorithm since it is telling me that 'abracadabra' is palindrome but it is not. RTL the sequence of the letters is wrong!
function isPalindrome(wordToCheck) {
for (var i = 0; i < wordToCheck.length; i++) {
var leftToRightWord = wordToCheck[i];
console.log('Left ' + leftToRightWord);
}
for (var j = wordToCheck.length - 1; j >= 0; j--) {
var rightToLeftWord = wordToCheck[j];
console.log('Right ' + rightToLeftWord);
}
if (leftToRightWord === rightToLeftWord) {
return 'La parola è palindroma';
} else {
return 'La parola non è palindroma';
}
}
alert(isPalindrome('abracadabra'));
Getting a NaN error in this addition function for script code, although there is no type conversion from string to int: Any suggestions?
var add = function(a, b) {
var i = 0,
sum = 0;
for (i = 0; i <= arguments.length; i++) {
sum += arguments[i];
}
return sum;
};
console.log(add(10, 20, 30, 40, 50));
For loop condition part should be i < arguments.length
arguments.length[arguments.length] will be undefined
In the last iteration of the for loop, code was trying to add 150 + undefined which resulted in NaN
Best way to figure out these type of problems is by debugging
Following are some debugging method
Use console statements and check what is happening
Use a debuggers and check line by line what is happening in your code
I personally use node debugger.
You check line by line what is happening in your code and check values
of variable on the fly
Following is working code
var add = function (a,b) {
var i = 0,
sum = 0;
for (i = 0 ; i < arguments.length ; i ++) {
sum += arguments[i];
}
return sum;
};
console.log(add(10,20,30,40,50));
You are setting the for loop's condition field incorrectly.
It should be:
(i = 0; i < arguments.length; i++)
(Notice the use of < instead of <=)
The problem is that you tried to add arguments[5] (because the length is 5, but arrays start at 0) which is undefined.
Number + undefined = NaN
I am pretty new to javascript and doing a course.I understand the return principle but when its nested in for example a nested for loop i get really confused.Would anyone mind to explain it to me?here is nothing nested but I got some example-code:
let generatePlayerBoard = (numberOfRows,numberOfColumns)=>{
const board = [];
for (var rowIndex = 0; rowIndex < numberOfRows.length; rowIndex++) {
const row = [];
for (var columnIndex = 0; columnIndex < numberOfColumns.length; columnIndex++) {
row.push(' ');
}
board.push(row);
}
return board;
};
console.log(generatePlayerBoard(2,3));
Thank you already for the help :D
The basics of nested returns is that a function can only return a value once, so once a function reaches its first return statement it ends the function.
Here's an example:
function hello () {
for(i = 0; i < 10; i++) {
if(i > 10) {
return 'Since i is never > 10 Im never reached so I never get to return anything'
} else {
return 'Hello!'
}
return 'The else statements returns before Im reached'
}
return 'Im never reached';
}
alert(hello());
Run that little script and you'll get an alert that says 'Hello!'
As mentioned before, in your script the return isn't nested, it's just run after all your other code has run.
Nesting is when you e.g. run:
if(1 < 2) {
if(2 < 3) {
// This second if is called a nested if because it's run inside another
// if statement
}
}
if(1 < 2 && 2 < 3) {
// This is also a form of nested if because it has the same effect as running
// the code above
}
Here is my code. I do not quite understand why the for loop runs only once, both inner and outer. nodeList.length and innerNodeList.length show appropriate values when I generate alert messages. I see that both i and j do not increment beyond 0. Kindly point out anything wrong with the code.
function getCategoryElements() {
var newCategoryDiv = document.getElementById("category");
var nodeList = newCategoryDiv.childNodes;
for (var i = 0; i < nodeList.length; ++i) {
var innerNodeList = nodeList[i].childNodes;
alert("innerNodeList Length" + innerNodeList.length.toString());
for (var j = 0; j < innerNodeList.length; ++j) {
if (innerNodeList[j].nodeName == "SELECT") {
alert("inside select Node value " + innerNodeList[j].nodeValue.toString());
document.getElementById("newCategories").value =
document.getElementById("newCategories").value + '<%=delimiter%>' + innerNodeList[j].nodeValue;
} else if (innerNodeList[j].nodeName == "TEXTAREA") {
document.getElementById("newCategoriesData").value =
document.getElementById("newCategoriesData").value + '<%=delimiter%>' + innerNodeList[j].nodeValue;
}
}
}
}
var newCategoryDiv, nodeList, innerNodeList, innerNode, i, j;
newCategoryDiv = document.getElementById("category");
nodeList = newCategoryDiv.childNodes;
for (i = 0; i < nodeList.length; ++i) {
innerNodeList = nodeList[i].childNodes;
alert("innerNodeList Length" + innerNodeList.length.toString());
for (j = 0; j < innerNodeList.length; ++j) {
innerNode = innerNodeList[j];
if (innerNode.nodeName === "SELECT") {
alert("inside select Node value " + innerNode.nodeValue.toString());
document.getElementById("newCategories").value += '<%=delimiter%>' + innerNode.nodeValue;
} else if (innerNode.nodeName === "TEXTAREA") {
document.getElementById("newCategoriesData").value += '<%=delimiter%>' + innerNode.nodeValue;
}
// Will this work?
alert('Does this alert appear');
}
}
I took the liberty to refactor your code and clean it up a little bit. In case you're not aware, all variables have function scope in Javascript, so no matter where you declare them within a single function, Javascript treats them as if the variable declaration is the first statement.
It appears that your code is syntactically correct, and so I think that the most logical place to look for a problem is that there could be an error occurring after the last alert function call.
In order to check this, try adding another alert function call to the end of the inner loop. If it doesn't run, you'll know this is the case.