I am trying to call a function in jQuery and the variable is coming back as undefined in the console
var divide = function(entry) {
var entry = number
for (var i = 1; i <= entry; i++) {
if (i % 5 === 0 && i % 3 === 0) {
return "pingpong";
} else if ( i % 3 === 0) {
return "ping";
} else if (i % 5 === 0 ) {
return "pong";
} else {
return i;
}
}
}
$(document).ready(function(){
$("form#number").submit(function(event){
var number = parseInt($("#userNumber").val());
var pingpong = divide (number);
$("#result").text(pingpong);
event.preventDefault();
});
});
Why do you need a for-loop for this ? Assigning number to entry will not help as number is within the local scope of $(document).ready which will be undefined for divide. As you are passing entry as an argument, use that for conditions
Try this:
var divide = function(i) {
if (i % 5 === 0 && i % 3 === 0) {
return "pingpong";
} else if (i % 3 === 0) {
return "ping";
} else if (i % 5 === 0) {
return "pong";
} else {
return i;
}
}
$(document).ready(function() {
$("form#number").submit(function(event) {
var number = parseInt($("#userNumber").val());
var pingpong = divide(number);
$("#result").text(pingpong);
event.preventDefault();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<form id='number'>
<input type="number" id='userNumber'>
<input type="submit">
<div id="result"></div>
</form>
Fiddle here
I think you may be confused about how arguments are passed into functions.
You have:
function divide ( entry ) { // defining divide
var entry = number; // this line is counter-productive
...
}
....
var number;
... divide(number); // calling divide
When you call the divide() function, the value of the variable number is automatically copied into the variable entry in divide(). Then you attempt to do the same thing with var entry = number; but number is not available in divide() so this fails. Lets suppose that number was globally available do this line did not cause an error. It might do what you want in this case, but a function whose argument is immediately ignored and overwritten is not very useful. Imagine you wanted to call it with two different values:
divide(number);
...
divide(someothernumber);
that wouldn't work because of the var entry = number; line -- you could never successfully pass someothernumber into divide(). Delete the line:
var entry = number;
from divide() and you will be much happier.
you try to delete "var entry = number"
Related
Hello I need to compare a previous result that I'm getting from an API with the new one. The thing is that I don't know the value that I'll be getting. Therefore, I use a random function and a variable called oldShowNumber that will store the old result from the API and compare it to the new one which I'll call newrandom.
I tried to use a counter so the next time it enters inside the counter > 1 condition. Am I overcomplicating myself?
This is my script:
var array= ["100", "200", "300", "300"]
var newrandom = array[Math.floor(Math.random() * array.length)];
let counter= 1
var oldShowNumber= "";
(function (param){
if(counter <= 1){
oldShowNumber += param
counter +=1
} else if( counter > 1){
if(oldShowNumber === param){
console.log("They are the same it should stop")
}
}
})(newrandom)
console.log(oldShowNumber)
You need to store the information whether you already have an old number and if yes, the value of said number.
A common technique is to initialize a variable with to undefined to refer to the first case and assign a number in the second case.
Therefore: Initialize oldShowNumber with undefined and replace
var oldShowNumber= "";
....
if (counter <= 1) {
...
} else if (counter > 1) {
...
}
with
var oldShowNumber; // identical with: var oldShowNumber = undefined;
....
if (oldShowNumber === undefined) {
...
} else {
...
}
function findRandomDayIndex() {
var dayindex = _.random(0, 39);
var slot = dayslots[dayindex]; // array of 40 objects
if(slot.filled === true || slot === undefined) {
return findRandomDayIndex();
} else {
return dayindex;
}
}
I get the error:
RangeError: Maximum call stack size exceeded iteration of the same function
How can better write the function?
You might try out this version
function findRandomDayIndex()
{
var dayindex = Math.random(0, 39);
while( ( slot = dayslots[dayindex] ) == null )
dayindex = Math.random(0, 39);
return dayindex ;
}
Please check the consistence of dayslot, in order to prevent infinite while-looping anyway
You don't need recursion to do this. With a little refactoring you can map your array to save indexes, then filter undefined and filled values and then get random item from that new array, e.g.:
function findRandomDayIndex() {
var notFilled = dayslots.map(function(value, index) {
return {
value: value,
index: index
};
}).filter(function(day) {
return day.value !== undefined && !day.value.filled;
});
if (!notFilled.length) {
// all items of dayslots are undefined or filled
// handle this case here
}
var dayindex = _.random(0, notFilled.length - 1);
return notFilled[dayindex].index;
}
Here's one that handles when all dayslots are filled. The sample code returns -1, but you can update it to return anything.
function findRandomDayIndex() {
// Create an array of indexes for items that aren't filled
var m = _.map(dayslots, function(v, k) {
if (!v.filled) {
return k;
}
});
// The array will have undefined for those already filled, so we use lodash without to remove them
m = _.without(m, undefined);
if (m.length === 0) {
// Handle when all slots are filled
return -1;
} else {
// return a random index
return m[_.random(0, m.length)];
}
}
// Lets create some test data
var dayslots = [];
for (var i = 0; i < 40; i++) {
dayslots.push({
filled: false
});
}
// Test our function
console.log(findRandomDayIndex());
If you change the filled to true, then you'll get a -1.
As #CodeiSir commented since no slot was free code was going into infinite loop. So I changed the code as below and it works fine. Thank you!
if (_.findWhere(dayslots, {filled: false}) !== undefined) {
var dayindex = _.random(0, 39);
var slot = dayslots[dayindex];
console.log(dayslots.length);
if(slot.filled === true || slot === undefined) {
return findRandomDayIndex();
} else {
return dayindex;
}
}
I wonder what's the most efficient way to write a function that takes two arrays of random integers and terminates when a pair of matching Integers is found.
In the following example there are two arrays, one larger then the other.
The larger array contains the potential dividents, the smaller array the divisors.
I'd like the function to calculate until it has found a pair of divident and divisor that are divisible without remainder.
EXAMPLE:
var listDivident = _.shuffle(_.range(1, 101));
var listDivisor = _.shufle(_.range(1, 11));
randomMatch = function (listDivident, listDivisor) {
/* until ((listDivident % listDivisor !== "undefined")
&& (listDivident % listDivisor === 0) {
...
}
*/
return {
matchDivident: matchDivident,
matchDivisor: matchDivisor
};
};
Is there something like an "until" function or construct in JS?
Thanks for your help!
Vin
Unless your arrays are very large, you can simply generate all valid pairs first and then pick a random one:
var pairs = [];
_.each(listDivident, function(a) {
_.each(listDivisor, function(b) {
if(!(a % b))
pairs.push([a, b])
})
});
result = _.shuffle(pairs)[0];
What you call "until" can be achieved by looping until you find what you need:
var listDivident = _.shuffle(_.range(1, 101));
var listDivisor = _.shufle(_.range(1, 11));
randomMatch = function (listDivident, listDivisor) {
var i = 0,
found = false,
dividentLength = listDivident.length,
divisorLength = listDivisor.length,
matchDivident = null,
matchDivisor = null;
while (!found && i < dividentLength && i < divisorLength) {
if (listDivident[i] % listDivisor[i] === 0) {
matchDivident = listDivident[i];
matchDivisor = listDivisor[i];
found = true;
} else {
i++;
}
}
return {
matchDivident: matchDivident,
matchDivisor: matchDivisor
};
};
EDIT: After that, just call the randomMatch() with the whole arrays:
alert(randomMatch(listDivident, listDivisor));
var math = {
Factorial:function(n) {
if (n == 0) {
return 1;
}
return n * Factorial(n - 1);
},
CalculateFactorial:function() {
var myValue = document.getElementById('myTextBox').value;
if (myValue.length == 0) {
alert("Please input the correct value!");
return;
}
var result = Factorial(myValue);
document.getElementById('title').innerHTML = result;
}
}
Hello guys. New to JavaScript and testing different things, coming from C# language things are pretty the same yet different.
I am trying to do something and no success.
Having the script above attached to a simple html button , trying to call the CalculateFactorial , math.CalculateFactorial(); , but what is wierd is that CalculateFactorial() doesn't actually see the Factorial() method. But in the math object I can see both methods. Wierd.
"JavaScript runtime error: 'Factorial' is undefined"
A good practice in JavaScript is to name all of your functions even if you assign them to a variable or use them like object's property. In your case just give a name to your Factorial function like this:
Factorial:function factorial(n)
{
if (n == 0)
{
return 1;
}
return n * factorial(n - 1);
},
For the problem of not seeing Factorial in your CalculateFactorial function just use this.Factorial when you invoke it.
This should fix the issue... if you want Factorial to be an internal only function (just a utility for the exposed CalculateFactorial) then you can do so this way:
var math = new function() {
var $this = this;
var Factorial = function(n) {
if (n == 0) {
return 1;
}
return n * Factorial(n - 1);
}
$this.CalculateFactorial = function() {
var myValue = document.getElementById('myTextBox').value;
if (myValue.length == 0) {
alert("Please input the correct value!");
return;
}
var result = Factorial(myValue);
document.getElementById('title').innerHTML = result;
}
}
The deeper design issue here is this is not particularly reusable javascript. You should consider pulling CalculateFactorial() out of the math object and into it's own handler... probably a click handler would be my guess like this:
var math = new function() {
var $this = this;
$this.Factorial = function(n) {
if (n == 0) {
return 1;
}
return n * $this.Factorial(n - 1);
}
}
$("#calcButton").click(function() {
var myValue = document.getElementById('myTextBox').value;
if (myValue.length == 0) {
alert("Please input the correct value!");
return;
}
var result = math.Factorial(myValue);
document.getElementById('title').innerHTML = result;
})
That happens beceause the Factorial method is part of the math object, and it doesn't reside in the global scope. When you try to call it directly, the parser will try to find that method into the global scope, and then, it will thrown an ReferenceError.
Since you're using the method inside the object itself, you can use the this keyword, because it will look into the object's context and find the method Factorial.
Another way of calling the Factorial method is by using the object, e.g: math.Factorial.
Take a look at the example below:
var math = {
Factorial: function(n) {
return n === 0 ? 1 : n * this.Factorial(n - 1);
},
CalculateFactorial: function(txt) {
document.getElementById('title').innerHTML = this.Factorial(txt.value);
}
};
document.getElementById('myTextBox').addEventListener('input', function() { math.CalculateFactorial(this); });
<input type="text" id="myTextBox" placeholder="Fatorial">
<div id="title"></div>
var userInput = prompt('enter number here');
var number = new Array(userInput.toString().split(''));
if (number ????){ //checks if the number is in a continuous stream
alert(correct);
}
else{
alert(invalid);
}
In Javascript, what can I do at "????" to check if it is in a continuous order/stream? Also how can I do this so that it only checks for this order/stream after a specific index in the array? Meaning the user enters say "12345678901234" which would pop up correct, but "12347678901234" would pop up invalid?(note there are two 7's) For the second part "3312345678901234" would pop up correct, how can this be implemented?
You can make a function that checks any string for a stream of continuous/increasing alpha-numeric characters starting at a given index like this:
function checkContinuous(str, startIndex) {
startindex = startIndex || 0;
if (str.length <= startIndex) {
return false;
}
var last = str.charCodeAt(startIndex);
for (var i = startIndex + 1; i < str.length; i++) {
++last;
if (str.charCodeAt(i) !== last) {
return false;
}
}
return true;
}
If it's numbers only and wrapping from 9 back to 0 is considered continuous, then it's a little more complicated like this:
function checkContinuous(str, startIndex) {
// make sure startIndex is set to zero if not passed in
startIndex = startIndex || 0;
// skip chars before startIndex
str = str.substr(startIndex);
// string must be at least 2 chars long and must be all numbers
if (str.length < 2 || !/^\d+$/.test(str)) {
return false;
}
// get first char code in string
var last = str.charCodeAt(0);
// for the rest of the string, compare to last code
for (var i = 1; i < str.length; i++) {
// increment last charCode so we can compare to sequence
if (last === 57) {
// if 9, wrap back to 0
last = 48;
} else {
// else just increment
++last;
}
// if we find one char out of sequence, then it's not continuous so return false
if (str.charCodeAt(i) !== last) {
return false;
}
}
// everything was continuous
return true;
}
Working demo: http://jsfiddle.net/jfriend00/rHH4B/
No need for arrays, just back though the string one character at a time.
When you hit a 0, substitute 10, and continue until the number
is not one more than the previous one.
function continuousFromChar(str, start){
start= start || 0;
var i= 0, L= str.length, prev;
while(L){
c= +(str.charAt(-- L)) || 10; // use 10 for 0
prev=+(str.charAt(L- 1));
if(c-prev !== 1) break;
}
return start>=L;
}
var s= "3312345678901234";
continuousFromChar(s,2)
/* returned value: (Boolean)
true
*/
This will do the checking in real-time entry, but a similar principle could be used to check an entry on a button submit or similar. I was not 100% sure as to which way you wanted it, so I went for the live method.
HTML
<input id="stream" type="text" />
Javascript
window.addEventListener("load", function () {
document.getElementById("stream").addEventListener("keyup", function (evt) {
var target = evt.target;
var value = target.value;
var prev;
var last;
var expect;
target.value = value.replace(/[^\d]/, "");
if (value.length > 1) {
prev = parseInt(value.slice(-2, -1), 10);
last = parseInt(value.slice(-1), 10);
expect = prev + 1;
if (expect > 9) {
expect = 0;
}
if (last !== expect) {
target.value = value.slice(0, value.length - 1);
}
}
}, false);
});
On jsfiddle
By changing the value here
if (value.length > 1) {
You can change where the checking starts.
Update: Ok, so it is function that you want, and you insist that it splits the string into an array. Then using the above as a reference, you could convert it to something like this.
Javascript
window.addEventListener("load", function () {
var testStrings = [
"0123456789012",
"0123456789",
"0123455555",
"555012345678901234",
"0123455555"];
function test(string, offset) {
if (typeof string !== "string" || /[^\d]/.test(string)) {
return false;
}
var array = string.split("");
var prev;
var last;
var expect;
return !array.some(function (digit, index) {
if (index >= offset) {
prev = parseInt(array[index - 1], 10);
last = parseInt(digit, 10);
expect = prev + 1;
if (expect > 9) {
expect = 0;
}
if (last !== expect) {
return true;
}
}
return false;
});
}
testStrings.forEach(function (string) {
console.log(string, test(string, 1));
});
});
On jsfiddle
As your question does not fully specify all possibilities, the above will return true for an empty string (""), of course you can simply add a check at the very beginning for that.
I also do not perform any checking for a valid number for your offset, but again this is something simple that you can add.
Of course these are just one (two) of many possible solutions, but hopefully it will set your mind in the right direction of thought.
There are some good answers here, but I would like to show a slight variation. I think it is important to showcase some different aspects of JavaScript and separating interests in code.
Functions as first class objects are cool - the exact rules for "continuous" can be changed with only changing the predicate function. Perhaps we should allow skipping numbers? No problem. Perhaps we allow hex digits? No problem. Just change the appropriate follows function for the specific rules.
This can be implemented generically because strings support indexing. This will work just as well over other array-like objects with an appropriate follows function. Note that there are no string-specific functions used in the continuous function.
Code also on jsfiddle:
// returns true only iff b "follows" a; this can be changed
function follows_1Through9WithWrappingTo0(b,a) {
if (b === "1" && a === undefined) {
// start of sequence
return true;
} else if (b === "0" && a === "9") {
// wrap
return true;
} else {
// or whatever
return (+b) === (+a) + 1;
}
}
function continuous(seq, accordingTo, from) {
// strings can be treated like arrays; this code really doesn't care
// and could work with arbitrary array-like objects
var i = from || 0;
if ((seq.length - i) < 1) {
return true;
}
var a = undefined;
var b = undefined;
for (; i < seq.length; i++) {
b = seq[i];
if (!accordingTo(b, a)) {
return false; // not continuous
}
a = b;
}
return true;
}
function assert(label, expr, value) {
if (!(expr === value)) {
alert("FAILED: " + label);
}
}
var follows = follows_1Through9WithWrappingTo0;
assert("empty1", continuous("", follows), true);
assert("empty2", continuous("foobar", follows, 6), true);
assert("skip", continuous("331234", follows, 2), true);
assert("good 1", continuous("123456789", follows), true);
assert("good 2", continuous("12345678901234", follows), true);
assert("bad seq 1", continuous("12347678901234", follows), false);
assert("bad seq 2", continuous("10", follows), false);
// here a different predicate ensures all the elements are the same
var areAllSame = function (b, a) {
return a === undefined || a === b;
};
assert("same", continuous("aaaaa", areAllSame), true);
Note that the skipping could also be extracted out of the continuous function: in a language with better "functional" collection support, such as C#, this is exactly what I'd do first.