Simpler way to format if statement? - javascript

I have an if statement:
if(firstString == "no" && secondString == "no" && thirdString == "no"){
// Do stuff here
}
Is there a prettier way to format this? Using false instead of "no" is not an option, since the data I'm checking is from an AJAX request and I don't control its output. Otherwise I'd write it this way:
if(!firstString && !secondString && !thirdString){
// Do stuff here
}
Thanks
UPDATE:
I know this is totally ridiculous, but it occurred to me that this might actually be the shortest way:
if(firstString + secondString + thirdString == "nonono"){
// Do stuff here
}

Given that the number of strings is known in advance, then you have 2 options as far as I can see..
Leave it as it is. The if statement isn't hard to read, and any alternate formats will either be as complicated or more complicated.
convert the strings to booleans when you retrieve the data from the AJAX request, so that you're storing TRUE or FALSE instead of "yes" and "no". That would allow you to use a your preferred if statement format, and might be more efficient than many string comparisons if you do a lot of them.
In the end, which you do is up to you, but personally I think it would be better to just stick with what you've got. Don't worry about formatting an if statement, it's pretty obvious what it does, and in my opinion doesn't need to change.

If( "no" == firstString && firstString == secondString && secondString == thirdString )

It was a little difficult to determine exactly what you are evaluating to true or false, but this can be tweaked a tad to get what you're looking for.
var checkStrings = function() {
var no = "no",
args = Array.prototype.slice.call(arguments);
for (var i = 0, len = args.length; i < len; i++) {
if (args[i] !== no) {
return false;
}
}
return true;
};
if (checkStrings(firstString, secondString, thirdString)) {
// Do stuff here
}

Sorry, wasn't thinking--this is if you were checking whether ANY were 'no'
if ($.inArray('no', [firstString, secondString, thirdString]) >= 0) {
// Do something if the value is 'no'
}
UPDATED ANSWER
Unfortunately, jQuery doesn't have the reduce() function (another Array extra introduced in JS 1.6, but not available in older browsers) which would do the trick nicely.
Here's one way to check if all are 'no':
var found = true;
$.each([firstString, secondString, thirdString], function (i, str) {
if (str !== 'no') {
found = false;
}
});
It may seem uglier, but it should be shorter if you have a lot more strings to check.
If you want it wrapped in a function you could do:
function allTrue (arr, checkStr) {
var found = true;
$.each(arr, function (i, str) {
if (str !== checkStr) {
found = false;
}
});
return found;
}
if (allTrue([firstString, secondString, thirdString], 'no')) {
// ...
}

function F(var value){
return value === "no";
}
if(F(firstString) && F(secondString) && F(thirdString)){
// Do stuff here
}

Another option, using jQuery.unique:
var uniques = $.unique([firstString, secondString, thirdString]);
if (uniques.length === 1 && uniques[0] === "no") {
// do stuff
}

Related

JavaScript - an array in if statement

I really need some help with this one, I've been struggling a lot trying to crack the example down on my own for way too long.. the whole issue is that I have an array that includes 15 pictures added by push property & createImage function, the problem though is that I've absolutely no idea how I could use the image in an if-statement like so:
if (check both if the image displayed is the first image within the array and answer equals 'x') return that's a good answer
that's a good answer } else (in case if either the image isn't the first one or answer doesn't equal 'x' return that's not a good answer
So far I've achieved the following, unfortunately enough the program omits the rule regarding the array
var answer = document.getElementById("answer");
var image = newArray[0];
function check() {
if (newArray[0] == true && answer.value == "C") {
window.alert("that's a good answer");
} else if (newArray[0] == true && answer.value == "c") {
window.alert("that's a good answer as well");
} else {
window.alert("that's unfortunately not a good answer");
}
}
Thanks in advance for any form of help
I obviously had to change things a bit since you don't give us the document or newArray, but after adding some dummy data and running it, it works. Can you be more specific about the error(s) you're running into?
Here's my solution:
var answer = "C";
var newArray = [true, false, false, true];
var image = newArray[0];
function check() {
if (image === true && answer == "C") {
window.alert("that's a good answer");
} else if (image === true && answer == "c") {
window.alert("that's a good answer as well");
} else {
window.alert("that's unfortunately not a good answer");
}
}
check();

jsbn2 modInverse returns undefined

I have found this library for big integers called jsbn2 by Tom Wu,
and it seemed to work well until I had to use modInverse method.
For some reason it returns undefined no matter what.
The method in the library is:
bnModInverse(m) {
var ac = m.isEven();
if((this.isEven() && ac) || m.signum() == 0) return new BigInteger(0);
var u = m.clone(), v = this.clone();
var a = new BigInteger(1), b = new BigInteger(0), c = new BigInteger(0), d = new BigInteger(1);
while(u.signum() != 0) {
while(u.isEven()) {
u.rShiftTo(1,u);
if(ac) {
if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
a.rShiftTo(1,a);
}
else if(!b.isEven()) b.subTo(m,b);
b.rShiftTo(1,b);
}
while(v.isEven()) {
v.rShiftTo(1,v);
if(ac) {
if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
c.rShiftTo(1,c);
}
else if(!d.isEven()) d.subTo(m,d);
d.rShiftTo(1,d);
}
if(u.compareTo(v) >= 0) {
u.subTo(v,u);
if(ac) a.subTo(c,a);
b.subTo(d,b);
}
else {
v.subTo(u,v);
if(ac) c.subTo(a,c);
d.subTo(b,d);
}
}
if(v.compareTo( BigInteger.ONE ) != 0) return new BigInteger(0);
if(d.compareTo(m) >= 0) return d.subtract(m);
if(d.signum() < 0) d.addTo(m,d); else return d;
// MODIFIED BY ATS 2008/11/22 FOR COMPATIBILITY TO Flash ActionScript
// if(d.signum() < 0) return d.add(m); else return d;
if(d.signum() < 0) return d.ope_add(m); else return d;
};
I used it with very long numbers, for ex.
var a = new BigInteger("26243431849380303664210129223718904471391758038739441955848319764858899645035");
var b = new BigInteger("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 16);
(fixed b value, ty Rudy Velthuis)
But the a.modInverse(b) returns undefined.
Is there something wrong with the method, that needs to be fixes?
How can I make it work?
OK.. after like hundreds of logs and stuff I finally found what is the problem in my case.
While the example value that I gave in question itself seems to actually work, there is a different problem with the method modInverse (again.. sorry if that mislead someone).
The problem with it (the modInverse method in jsbn2) is that it doesn't know what to do with negative numbers (while the Java modInverse knows).
My solution to this was to check if the value that I will give it is positive and if not, I prepared it (thanks to this topic for explaining how):
if(a.compareTo(ZERO)<0)
{
a = a.negate(); //make it positive
a = a.mod(b); //get modulo
a = b.subtract(a); //get remainder of modulo
}
I don't know if this is the best solution to it (surely not) but it seems to work.
The result values that I tested are now equal to those of Java's modInverse.
Hope this helps anyone who get lost just like me here :3

Javascript dynamic conditioning

I want to build a IF condition which is built dynamically based on the parameters it gets. More over, this is expected to be built as a plugin.
For instance, there are 3 parameters for student object, called age,name, phone_numbers. Also, there is a option object for selection parameters.
In the condition,
if(student.age >option.age & student.name == option.name & student.phonenumbers == option.phonenumbers ){
// do stuff
}
If any parameter is missing, it should not be included in the condition. For example, assume, in case option.name is undefined, then the if condition should be prepared as following,
if(student.age >option.age & student.phonenumbers == option.phonenumbers ){
// do stuff
}
Moreover, why this kind of thing is required is, here an array of (500 objects) students objects are iterated. The above condition can be splitted into seperat conditions, but then the iteration will be multipled by the number of conditions !!!. So I m looking for a way to add all conditions into one.
However, my approach is, create the expression as a string and then execute it with eval(..),but as far as I know that using eval can lead vulnerabilities.
Any one let me know a way to implement a dynamic conditions.
Note that the JavaScript and operator is &&.
For your example, this should work:
if((!student.age || student.age>option.age) &&
(!student.name || student.name==option.name) &&
(!student.phonenumbers || student.phonenumbers==option.phonenumbers)
) {
}
How about
function testStudent(student,option) {
var res = [];
var test = true;
if (student.age) res.push(student.age > option.age);
if (student.name) res.push(student.name == option.name);
if (student.phonenumbers) res.push(student.phonenumbers == option.phonenumbers);
for (var i=0;i<res.length;i++) {
test = test && res[i];
}
if (res.length > 0 && test) {
//do stuff
}
}
generic:
function testObjects(obj1,obj2) {
for (var o in obj1) { // assuming obj2 is a superset of obj1
if (o === "age" && obj1.age <= obj2.age) return false;
if (obj1.hasOwnProperty(o) && obj1[o] != obj2[o]) return false;
}
return true;
}
var ok = testObjects(student,option);
You can have your conditions in functions and those functions in an Array. so then you can do a loop in the Array and call every function (condition).
var aConds = [];
function firstCond(params) {return (params<0)};
function secondCond(params) {return(params!='hi')};
aConds.push(firstCond);
...
for(var i=0;i<aConds.length;i++)
{
if(!aConds[i](params)) console.log("a condition has not been meet");
}
Would it work to allow undefined in each condition?
if((student.age == undefined || student.age > option.age) && (student.name == undefined || student.name == option.name) ...

Alternative solution to underscore.js

I have created a game that is based on a grid being populated with words
In my code I have a small bit of underscore.js that helps my words fit in the space available in the grid without breaching the grids barriers.
I understand that it is very powerful java script and don't personally have a problem with it. But my team manager would like to get rid of it for some jQuery that will provide the same solution as there is only one function and would save me having a whole library. How I would replace this with some jQuery?
function getWordToFitIn(spaceAvail, wordlist) {
var foundIndex = -1;
var answer = _.find(wordlist, function (word, index) {
if (word.length <= spaceAvail) {
foundIndex = index;
return true;
}
});
if (foundIndex == -1) {
answer = getXSpaces(spaceAvail);
_.find(wordlist, function (word, index) {
if (word[0] == " ") {
foundIndex = index;
return true;
}
});
}
if (foundIndex != -1) {
wordlist.splice(foundIndex, 1);
}
return answer;
}
As far as I can see, the only underscore method youre using is _.find. But I don’t think you are using it as it was intended. It looks like you are simply looping and returning true when a criteria is met.
You can use the native forEach if you don’t have legacy support, or use a shim. Or you can use the jQuery.each method.
The first loop could probably (I’m not 100% sure about the answer variable) be written like this:
var answer;
$.each(wordlist, function(index, word) {
if (word.length <= spaceAvail) {
foundIndex = index;
answer = word;
return false; // stops the loop
}
});
And the second one:
$.each(wordlist, function (index, word) {
if (word[0] == " ") {
foundIndex = index;
return false;
}
});

Javascript function to compare two versions

Im writting a function to compare 2 versions, and return true if the second is bigger then first version.
but my algorithm have a "hole", and I cant figure out how fix.
function compareversion(version1,version2){
var result=false;
if(typeof version1!=='object'){ version1=version1.toString().split('.'); }
if(typeof version2!=='object'){ version2=version2.toString().split('.'); }
for(var i=0;i<(Math.max(version1.length,version2.length));i++){
if(version1[i]==undefined){ version1[i]=0; }
if(version2[i]==undefined){ version2[i]=0; }
if(version1[i]<version2[i]){
result=true;
break;
}
}
return(result);
}
this exemples return as expected
compareversion('1','1') //false
compareversion('1','1.0.0') //false
compareversion('2.0','1.0.0') //false
compareversion('1.1','1.2') //true
compareversion('1','1.0.0.1') //true
but this
compareversion('1.1.0','1.0.1') //return true but should be false
This should work:
function compareversion(version1,version2){
var result=false;
if(typeof version1!=='object'){ version1=version1.toString().split('.'); }
if(typeof version2!=='object'){ version2=version2.toString().split('.'); }
for(var i=0;i<(Math.max(version1.length,version2.length));i++){
if(version1[i]==undefined){ version1[i]=0; }
if(version2[i]==undefined){ version2[i]=0; }
if(Number(version1[i])<Number(version2[i])){
result=true;
break;
}
if(version1[i]!=version2[i]){
break;
}
}
return(result);
}
The reason compareversion('1.1.0','1.0.1') fails is that your code first compares 1 to 1, then 1 to 0 (it does not break here since it only breaks if version1[i] < version2[i]) and then 0 to 1.
Since 0 < 1, it returns false.
If version1 is at that index bigger, you know it should return false. You only need to continue if they are equal.
if(version1[i]<version2[i]){
result=true;
break;
}
if(version1[i]>version2[i]){
result=false;
break;
}
// Will only get here if both are equal, in all other
// cases you broke out of the loop. So only continue
// checking the next index when this one was equal.
Your problem is that if you have 1.1.0 and 1.0.1,
the function does not reach the break when you need it to
if(version1[i]<version2[i]){
result=true;
break;
}
it keeps comparing the numbers until the end.
you get 1<1 == false, the if does not run
then you get 1<0 == false, the if does not run
and then 0<1 == true, if makes result = true.
you would need:
if(version1[i]<version2[i]){
return true;
}else
if(version1[i]>version2[i]){
return false;
}
None of these answers is optimal for the following reasons:
your parameters being passed in can be strings. later on you convert them to an array. this is expensive and goes against good coding practice. NEVER change the type of a variable after it has been initialised! Create a new variable to hold the array.
The function continues through the loop even after it has enough info to return with a result.
You basically want to start at the major version and work down to the minor version. As soon as you find one that is not equal, you want to return. It is standard when doing a greater than, less than operation in function(a,b) that the return value of the function should be :
1 = a > b
-1 = a < b
0 = a===b
Otherwise, anyone calling this function would not know what it returns true for unless they look at the internals of it. If minified and obfuscated, this could be a waste of time.
I have rewritten and improved the function with this in mind.
function (versionA, versionB) {
var arrA,
arrB;
arrA = typeof versionA !== 'object' ? versionA.toString().split('.') : versionA;
arrB = typeof versionB !== 'object' ? versionB.toString().split('.') : versionB;
for (var i = 0; i < (Math.max(arrA.length, arrB.length)); i++) {
arrA[i] = typeof arrA[i] === 'undefined' ? 0 : Number(arrA[i]);
arrB[i] = typeof arrB[i] === 'undefined' ? 0 : Number(arrB[i]);
if (arrA[i] > arrB[i]) {
return 1;
}
if (arrA[i] < arrB[i]) {
return -1;
}
}
return 0;
};
version1 = version1.toString();
version2 = version2.toString();
var matchFound = false;
if(version1.length != version2.length){
//Different Versions
}else{
//They are the same length so compare each element
FIND:
for(var i = 0; i < version1.length; i++){
var match = version[i].match(version2[i]){
if(match == ""){
//Match found
matchFound = true;
break FIND;
}
}
return matchFound;
Using localeCompare works pretty well.
The below link have my solution used in comparing version number
https://stackoverflow.com/a/73749865/13970597

Categories

Resources