Can't find issue in simple js for-loop - javascript

I am trying out javascript for (more-or-less) the first time and find myself completely baffled by the following .js script.
var pair = newArray();
var id = newArray();
var pairs = 2;
function newGame(){
var randomid = 0;
alert("newGame() called!");
// Sets a specific part of the image sprite to each pair[].
for (var i=0 ;i < pairs; i++){
alert("For loop started!");
pair[i] = "url(Cardfront.jpg) -"+100 * Math.floor((Math.random()*13)+0)+"px -"+200 * Math.floor((Math.random()*4)+0)+"px";
// For every pair, assigns a part of the image sprite to two id[]-s.
alert("Pair " + i + "is " + pair[i]);
for(var j=0; j < 2; j++) {
//the range of possible id-s the total number of cards - double the amount of pairs.
randomid = Math.floor((Math.random()*pairs*2)+0);
if (id[randomid] === null){
id[randomid] = pair[i];
alert("ID " + randomid + "is " + id[randomid]);
}
else j--;
}
}
alert("This is called after the for loop!");
}
When I call newGame() through a button, I receive the "newGame() called!" and then "This is called after the for loop!" alerts, then nothing.
I've spent a while googling and poking around trying to figure this out, but I'm at the end of my wits, it seems.

Change newArray() to new Array() I believe that is what is causing your error sir.
Good luck!
EDIT: To fix the other error I found you have the following:
if (id[randomid] === null) {
with 3 = sign. Change it to just two:
if (id[randomid] == null) {
and it should work the way you expect it to.
Unless you are really trying to use the strict comparisson operator, then there is something else bugging your code.

In this piece of code:
if (id[randomid] === null){
id[randomid] = pair[i];
alert("ID " + randomid + "is " + id[randomid]);
}
else j--;
You can't mix the if/else shorthand:
if(something)
//Do X
else
//Do y
With it's bracket notation:
if(something){
//Do X
} else {
//Do y
}
So, put brackets around your else:
if (id[randomid] === null){
id[randomid] = pair[i];
alert("ID " + randomid + "is " + id[randomid]);
} else {
j--;
}

The for loop should read:
for (var i=0; i<pairs.length; i++) {
...
}
pairs is being coerced into a numeric value (zero in this case), so the first comparison (i<pairs) will be the same as 0<0 which will never true.
:-(

Related

How to know when a for loop is done without knowing how many iterations there will be?

using a for-loop in javascript i´m getting a not known amount of id´s, they´re not in an array but coming one by one.
is there a way to get an alert when there are no more id´s to retrieve meaning the for loop is done?
i can´t wrap my head around this, any help would be greatly appreciated.
thanks!
edited with code for clarification.
function iterateDevices(api) {
var count = api.getcount("devices"); var apiPath = dequotePath(api);
for (var i = 0; i < count; i++) {
var deviceApi = new LiveAPI(apiPath + " devices " + i); if (deviceApi) {
var deviceName = deviceApi.get("name"); var deviceid = deviceApi.id; //var
deviceName = deviceApi.get("parameters"); var className =
deviceApi.get("class_name"); var deviceApiPath = dequotePath(deviceApi);
var chainsCount; var chainApi; var j;
if ((className == "DrumGroupDevice") || (className ==
"AudioEffectGroupDevice") || (className == "InstrumentGroupDevice")){
//post(deviceName + " id " + deviceid + "\'\n"); //outlet(0,deviceid);
// arr.push(deviceName);
if (deviceApi.get("can_have_chains") == 1) { chainsCount =
deviceApi.getcount("chains"); // only racks have chains for (j = 0; j
< chainsCount; j++) { // post("id" + deviceid + " found device " +
deviceName + " at path \'" + deviceApiPath + "\'\n");
//outlet(0,deviceid); chainApi = new LiveAPI(deviceApiPath + " chains
" + j); iterateDevices(chainApi);
myFunction(); } chainsCount = deviceApi.getcount("return_chains");
// only racks have chains for (j = 0; j < chainsCount; j++) {
//post("2 found device " + deviceName + "id"+deviceid + " at path
\'" + deviceApiPath + "\'\n"); // outlet(0,deviceid); chainApi = new
LiveAPI(deviceApiPath + " return_chains " + j);
iterateDevices(chainApi);
}
}
}
}
}
} iterateDevices.local = 1;
The purpose of a for loop is to deal with a known number of iterations. If you want to deal with an unknown number of iterations, you would use a while loop.
Of course, this is programming, so lets look at the crazy things we can do:
Iterate over a collection. We dont necessarily know how many things
are in the collection, but we may want to iterate over all of them.
The number of things in the collection might even change as we're
iterating.
We can change how we iterate through the loop. That whole i++ part?
What if we replace it with i += 2? Or what if it's i -=1? Or i += j
and j changes while we're iterating?
We can change how we break out of the loop. You can put a break
statement in there to break out of the loop anytime. You can also
change the conditional of the loop. What if i < 100 is replaced by
i<j? Or what if we replace it with i<100 || q == true?
You may use a while loop instead of a for and insert a condition to terminate the loop.
Using pseudo-code, you could do something like:
other_ids = True // boolean var
while(other_ids) {
// do what you have to do
other_ids = FuncionToCheckWhetherThereAreNewIds
}
FuncionToCheckWhetherThereAreNewIds should be a function that gives you true if there are new ids and false if there are not.

What is the problem with my pangram javascript?

Pangram is a function that gets an input and check it if it has all alphabet ,This is my code i used ASCII code :
function pangram(x) {
var a;
for (var i = 97; i < 122; i++) {
a = "&#" + i + ";";
if (x.toLowerCase().includes(a) !== true) {
break;
}
}
if (i === 122) {
return true
} else {
return false
}
}
I think the problem is a = "&#" + i + ";" ; but i don't know why it can be a problem , it should work ...
You need to use charCodeAt() instead of making a manual one. Replace if condition to this :
if(x.toLowerCase().includes(String.fromCharCode(i))!==true)
You have come close to the answer, yet there are a few issues with the code,
a = "&#" + i + ";";, what does this do? You can use String.fromCharCode(65); to get the character for a given ASCII value. More info: https://www.w3schools.com/jsref/jsref_fromcharcode.asp
You can just exit the loop and the function if a character was not found, no point continuing after that point.
function pangram(x) {
var a;
for (var i = 97; i < 122; i++) {
a = String.fromCharCode(i);;
if (x.toLowerCase().includes(a) !== true) {
// if atleast one letter was not found, we exit the function and the loop
return false;
}
}
// if it comes here, that means all the letters were found
return true;
}
var isPangram = pangram("The quick brown fox jumps over the lazy dog");
console.log(isPangram);

Logical error in my function prevents count++ from working

I am struggling to find the last logical error in this code it still returns Found 0 wishes, rather than 12.
var msg = 'I wish to wish the WISH you wish to wish but if you wish '
+ 'the WISH the witches wish I won\'t wish the WISH you wish '
+ 'to wish';
document.writeln('Found ' + countTerms(msg) + ' wishes.');
function countTerms(phrase) {
var i = 1;
var count = 0 ;
var terms = phrase.split(' ');
for (i = 0; i < terms.length - 1; i++){
if (terms[i].toUpperCase() == 'WISH'){
return count++;
}
}
}
With return inside the for loop, for the very first match, we are returning count and then incrementing, which means function will return 0 there itself. And if there was no such match it will return undefined (default return).
You will need to return count after the for loop. Also, the condition in for loop has to be i < terms.length otherwise, we will miss the last value in the array.
var msg = 'I wish to wish the WISH you wish to wish but if you wish '
+ 'the WISH the witches wish I won\'t wish the WISH you wish '
+ 'to wish';
document.writeln('Found ' + countTerms(msg) + ' wishes.');
function countTerms(phrase) {
var i = 1;
var count = 0 ;
var terms = phrase.split(' ');
for (i = 0; i < terms.length; i++) {
if (terms[i].toUpperCase() == 'WISH'){
count++;
}
}
return count;
}
Please note, you can also simplify your code using Array.reduce. After splitting string into array, filter in only those values of array which have the value 'wish' and then return the length of the filtered array.
var msg = 'I wish to wish the WISH you wish to wish but if you wish '
+ 'the WISH the witches wish I won\'t wish the WISH you wish '
+ 'to wish';
document.writeln('Found ' + countTerms(msg) + ' wishes.');
function countTerms(phrase) {
return phrase.split(' ').filter(p => p.toUpperCase() === 'WISH').length;
}
You always return the first count directly, which is 0 at that point. To keep counting, just do count++ in the loop, and return count; after the loop is done.
Don't return inside loop
for (i = 0; i < terms.length - 1; i++){
if (terms[i].toUpperCase() == 'WISH'){
count++;
}
}
// Return hear
return count;
It's because you're returning a pre
-incremental value. This means that the variable is not updated until the return statement has finished running. to fix your code, change
return count++
to this
count++
and then return count at the bottom of the function, after the for loop.
There are two mistakes. Return the count after the loop.
Another one is in the for loop: you either use i < terms.length or i <= terms.length -1; or else you will miss the last 'wish'
var msg = 'I wish to wish the WISH you wish to wish but if you wish ' +
'the WISH the witches wish I won\'t wish the WISH you wish ' +
'to wish';
console.log('Found ' + countTerms(msg) + ' wishes.');
function countTerms(phrase) {
var count = 0;
var terms = phrase.split(' ');
for (let i = 0; i < terms.length; i++) {
if (terms[i].toUpperCase() === 'WISH') {
count++;
}
}
return count;
}

Get max or min value from associative array with function and parameters

Here is the code as far as I got it right now:
<!DOCTYPE html>
<html>
<body>
<button onclick="scanarray('a', 'max')">Test with a, max</button>
<button onclick="scanarray('b', 'min')">Test with b, min</button>
<p id="demo">test</p>
<script>
var array = [{"a":1},{"b":3},{"a":6},{"b":10}];
var max = null;
var min = null;
var value = null;
function scanarray(scanval, searchterm) {
if (array.length < 1) {
return -1;
}
if(searchterm == "max"){
max = Math.max.apply(Math,array.map(function(e){return e.scanvalue;}))
}else if (searchterm == "min"){
min = Math.min.apply(Math,array.map(function(e){return e.scanval;}))
}else
{document.getElementById("demo").innerHTML = "Only max and min available";}
if(searchterm == "max"){
document.getElementById("demo").innerHTML = "Search: " + scanval +" "+ "Value: " + max;
}
if(searchterm == "min"){
document.getElementById("demo").innerHTML = "Search: " + scanval +" "+ "Value: " + min;
}
}
</script>
</body>
</html>
The above should give me a and 6 or b and 3 as results. However I get NaN as result for the value part. When using "return e.a" in the Math section and only having a as keys it works.
I want to be able to determin the max or min value of a key I enter as parameter to the function.
Hope you can help me here.
Thanks in advance.
TheVagabond
There are some naming mess in your code. For example scanvalue is name of your function but you are trying to reach it as a parameter of e(e.scanvalue). I should be scanval. But still there are some problems. You can't reach property "a" or "b" of e if e.scanval. You're trying to reach variable of variable.
Then, you should use e[scanval]. It returns you to value of "a" or "b". But if object doesn't have one of them? Then you should add "|| 0" to get correct value. (Instead of NaN or undefined) It means that; use e[scanval] if its valid, if not use 0.
Use this;
return e[scanval] || 0;
If your boundaries include some negative values, use something like -9999 or -Infinity.
You are getting Nan because e.scanvalue returns undefined in your case.
Try using custom function.
function getValue(arr){
var res = [];
for(var j = 0; j < arr.length; j++)
{
for(var anItem in arr[j])
{
res.push(arr[j][anItem]);
}
}
return res;
}
and call this function like
max = Math.max.apply(Math,getValue(array))
and
min = Math.min.apply(Math,getValue(array))
accordingly.
Hope this helps!!!!

JavaScript error: Uncaught TypeError: undefined is not a function on line 4; I Don't Know What I Did Wrong

I'm trying to get a user to write a sentence and then have the computer confirm each word in a separate "confirm window" without using spaces.
In order to figure out if this code is the correct code to do this task I have to run the code, but
I'm getting the error listed in the title for line four. First, I don't understand what the error is saying. And if it is telling me that on line four the ifstatement is not a function and it can not run it, then how come?
<script>
function sentenceFinder (sentence){
for (counter = 0; counter < sentence.length; counter++){
if (sentence.substring(counter, counter + 1) !== " "){
words.push(sentence.substring(counter, counter + 1));
}
else {
comfirm(words[0]);
}
};
}
var x = prompt("Please type in the sentence that will be seperated.")
sentenceFinder(x)
var words = []
</script>
You have two issues which are causing errors.
You are using subscript where I think you intended to use substring.
You are using words before you set it to an array.
I think this is what you intended to write.
function sentenceFinder (sentence){
for (counter = 0; counter < sentence.length; counter++){
if (sentence.substring(counter, counter + 1) !== " "){
words.push(sentence.substring(counter, counter + 1));
}
else {
comfirm(words[0]);
}
};
}
var words = [];
var x = prompt("Please type in the sentence that will be seperated.");
sentenceFinder(x);

Categories