Minimize the use of "Many repeated if statement" - javascript

I got a script using TONS of if statement to do a task... But....
Most of them repeated like:
if (parent.getObject()=='apple') {
if (datatype('fruit')){
//do a
parent.setObjectType('fruit');
}
else if (datatype('beverage')){
//do a
parent.setObjectType('beverage');
}
}
else if (parent.getObject()=='banana') {
if (datatype('fruit')){
//do a
parent.setObjectType('fruit');
}
else if (datatype('beverage')){
//do a
parent.setObjectType('beverage');
}
}
else if (parent.getObject()=='coconut') {
if (datatype('fruit')){
//do a
parent.setObjectType('fruit');
}
else if (datatype('beverage')){
//do a
parent.setObjectType('beverage');
}
}
else if (parent.getObject()=='Dewberry') {
if (datatype('fruit')){
//do a
parent.setObjectType('fruit');
}
else if (datatype('beverage')){
//do a
parent.setObjectType('beverage');
}
}
Is it possible for me to minimize the use of those repeated codes?
I don't want to use up all the spaces only with lines of if else statement...

I'm not sure whether your actual code is a bit more diverse, but what you have posted can exactly be replicated by
if (['apple', 'banana', 'coconut', 'Dewberry'].some(function(fruit) {
return parent.getObject()==fruit;
}) {
var type = ['fruit', 'beverage'].find(datatype);
if (type) {
//do a
parent.setObjectType(type);
}
}
(where the find function is something like the following
Array.prototype.find = function(predicate, context) {
for (var i=0; i<this.length; i++)
if (predicate.call(context, this[i], i))
return this[i];
return null;
};

Without seeing more code maybe you could use something like this:
function doTask(a, b) {
var as_string = a + ";" + b;
switch (as_string) {
case "1;1":
//code when a=1 and b=1
break;
case "1;2":
//code when a=1 and b=2
break;
}
}
var a = 1;
var b = 1;
doTask(a, b);

You may or may not be able to reduce if statements depending on your code.
For example if you're adding odd numbers from 0 to n, you an either loop from 0 to n and use if statements to check if the number is odd. However if you happen to know Gauss's rule 1/2*n*(n+1), you can compute this value in one line without any looping or conditional statements (by removing the k(k+1); k even numbers).

You can simply use The switch Statement, it's more efficient in the case you have many possible values:
switch (parent.getObject()) {
case "apple":
switch (datatype) {
case "fruit":
//Task //do task a
//do task b with value 1
break;
case "beverage":
//do task a
//do task b with value 2
break;
}
break;
case "banana":
// Task a with ...
break;
// And put all your possible values
}
You have just to manage the possible vlaues of parent.getObject() and datatype.

Related

How to write Cleaner Nested Conditions in JavaScript

Using if statement we will get so much of nesting and if statement readability will reduce if the code size increases.
If Statement example:
if (item) {
if (item === 'palladium') {
printPalladiumPrice();
} else if (item === 'silver') {
printSilverPrice();
} else if (item === 'gold') {
printGoldPrice();
} else if (item === 'platinum') {
printPlatinumPrice();
} else if (item === 'diamond') {
printDiamonPrice();
} else {
printAllItemPrice();
}
}
The same problem we will face with the Switch statement. If the size increases the Switch Case readability will reduce as shown below.
Switch Case example:
switch (item) {
case 'palladium':
printPalladiumPrice();
break;
case 'silver':
printSilverPrice();
break;
case 'gold':
printGoldPrice();
break;
case 'platinum':
printPlatinumPrice();
break;
case 'diamond':
printDiamondPrice();
break;
default:
printAllItemPrice();
}
If we use JSON OBJECT our conditions will reduce to one single if statement and code will be much readable. Below is the example to write Cleaner Nested Conditions using the JSON Object.
JSON Object example:-
const itemObj = {
'palladium': printPalladiumPrice,
'silver': printSilverPrice,
'gold': printGoldPrice,
'platinum': printPlatinumPrice,
'diamond': printDiamondPrice,
};
if (item in itemObj) {
itemObj[item]();
}
Our conditions are now reduced to one single if and code is much readable.

Javascript coding quiz not adding up

I'm trying to do a simple quiz where it should sum the correct answers and incorrect answers. The thing is although I put two out of three correct answers, I keep getting the same result for the correct and incorrect array: 0. So there must be something wrong at the end, in the evaluate function. Thanks in advance
var responsesArray= [];
var correct=[];
var incorrect= [];
function question2() {
var firstQuestion = prompt('Does null === 0 ? (Yes or No)')
// why do you need to convert the answer to lowercase?
if (firstQuestion.toLowerCase() === 'yes') {
firstQuestion = true
} else if (firstQuestion.toLowerCase() === 'no') {
firstQuestion = false
} else {
// what if the user writes something other than yes or no?
// they will have to answer the question again
alert("Please answer either Yes or No");
return question2();
}
responsesArray.push(firstQuestion); // add the true or false value to the responses array
}
question2();
function question3() {
var js = prompt('What was the original name for JavaScript: Java, LiveScript, JavaLive, or ScriptyScript?');
js = js.toLowerCase();
switch (js) {
// your own answers
case "livescript":
console.log("Correct!");
break;
case "Java":
console.log("wrong");
break;
case "JavaLive":
console.log("wrong");
break;
case "ScriptyScript":
console.log("wrong");
break;
default:
console.log("Sorry the answer is LiveScript");
}
responsesArray.push(js);
var mine = prompt('What coding language is exclusively related to the back-end: Ruby, JavaScript, HTML?');
mine= mine.toLowerCase();
switch (mine) {
// your own answers
case "ruby":
console.log("Yeah!");
break;
case "html":
console.log("ouuu I'm sorry for you");
break;
case "javascript":
console.log("Yeah but so so");
break;
}
responsesArray.push(mine);
}
question3();
function evaluate(responsesArray)
{
for (var i = 0; i < responsesArray.length; i++)
{
if (responsesArray[i] === true|| "livescript" || "ruby")
{
correct++;
} else{
if (responsesArray[i] !== true|| "livescript" || "ruby") {
incorrect++;
}
}
}
Define an array to store the correct answer and then compare correct and user response and easily can identify whether it is correct or not.
Please check below snippet.
var responsesArray= [];
var correct=0;
var incorrect= 0;
//Correct answer key initialize
var index = 0;
//Initialize array to store correct answer.
var correctAnswers = [];
function question2() {
//Save correct answer.
correctAnswers[index++] = "yes";
var firstQuestion = prompt('Does null === 0 ? (Yes or No)')
// why do you need to convert the answer to lowercase?
if (firstQuestion.toLowerCase() === 'yes') {
console.log("correct");
firstQuestion = 'yes'
} else if (firstQuestion.toLowerCase() === 'no') {
console.log("in-correct");
firstQuestion = 'no'
} else {
// what if the user writes something other than yes or no?
// they will have to answer the question again
alert("Please answer either Yes or No");
return question2();
}
responsesArray.push(firstQuestion); // add the true or false value to the responses array
}
question2();
function question3() {
//Save correct answer.
correctAnswers[index++] = "livescript";
var js = prompt('What was the original name for JavaScript: Java, LiveScript, JavaLive, or ScriptyScript?');
js = js.toLowerCase();
switch (js) {
// your own answers
case "livescript":
console.log("Correct!");
break;
case "Java":
console.log("wrong");
break;
case "JavaLive":
console.log("wrong");
break;
case "ScriptyScript":
console.log("wrong");
break;
default:
console.log("Sorry the answer is LiveScript");
}
responsesArray.push(js);
//Save correct answer.
correctAnswers[index++] = "ruby";
var mine = prompt('What coding language is exclusively related to the back-end: Ruby, JavaScript, HTML?');
mine= mine.toLowerCase();
switch (mine) {
// your own answers
case "ruby":
console.log("Yeah!");
break;
case "html":
console.log("ouuu I'm sorry for you");
break;
case "javascript":
console.log("Yeah but so so");
break;
}
responsesArray.push(mine);
//Call function to evaluate correct or incorrect answer
evaluate(responsesArray,correctAnswers)
}
question3();
function evaluate(responsesArray,correctAnswers)
{
for (var i = 0; i < responsesArray.length; i++)
{
//Match response with correct answer.
if (responsesArray[i] === correctAnswers[i])
{
correct++;
} else{
if (responsesArray[i] !== correctAnswers[i]) {
incorrect++;
}
}
}
alert("Correct : "+correct+" and Incorrect : "+incorrect);
}
The way you test for correct answers is wrong. Instead define an array with the correct answers and verify them as follows:
var correct = incorrect = 0; // better initialise your variables
function evaluate(responsesArray) {
var correctAnswers = [true,"livescript","ruby"];
for (var i = 0; i < responsesArray.length; i++) {
if (responsesArray[i] === correctAnswers[i]) {
correct++;
} else {
incorrect++;
}
}
}
What you had was:
if (responsesArray[i] === true|| "livescript" || "ruby"){
But this means:
if the answer was true, or .... "livescript" is true, or ... "ruby" is true, then
As JavaScript considers strings to be truthy, the if condition would always be true.
Note also that there is no need to do a second if, since the else part is only executed if the first if condition was false, which means you already have filtered for the cases where the answer was wrong.
Finally, your counter variables should be defined before you start incrementing them. It works without this definition, but if one of the two variables is not incremented, it will still be undefined after your call to evaluate. Better always define your variables.

The following code only produces an output true. How to debug it?

I have the following code to generate prime numbers. However, instead of generating prime number, it generates the entire list on numbers from 2 to the number that is fed into the function. How to resolve this?
var i = 2;
var primeCheck = function(number){
while(i<number){
if(number%i===0)
{
break;
}
i++;
}
if (i===number)
{
return true;
}
};
var primeGen = function(limit){
for(k=2; k<=limit; k++)
{
if(primeCheck(k)){
console.log(k);
}
}
};
primeGen(10);
EDIT: I realized that I was quite unclear with my question. So I updated it. My guess is that the "return true" is causing this nuisance. Therefore I had asked my previous question based on that.
If you want to return something you have to return instead of alert; break. I would consider refactoring this though. First of all, you should never have a function that performs such a simple task rely on an outside variable. Keep it modular.
function isPrime(num) {
for (var i = 2; i < num; i++) {
if (num % i === 0) {
return false;
}
}
return num > 1
}
This will return true if the number is prime and false otherwise. This is useful because you now have the flexibility to do multiple things with it. If you want to return true or false, it does that. If you want to output something else like "prime" or "not prime" it's very easy to wrap further.
function isPrimeText(num) {
return isPrime(num) ? "Prime" : "Not Prime"
}
Your if condition that returns the alert runs with primecheck() without parameters. Correct it to:
if (primeCheck(11)) {
alert("prime");
}
Also, remove the last line with the call to primeCheck(11).
Just use primeCheck(11) in your condition where you want to put alert
There is some error in your logic, when I try with primeCheck(12) it does not gives intended result.
var i = 2;
var primeCheck = function(number){
while(i<Math.floor(Math.sqrt(number))){
if(number%i===0)
{
alert("Not a prime");
break;
}
i++;
}
if (i===Math.floor(Math.sqrt(number)))
{
return true;
}
};
//now check for prime or not prime
if(primeCheck(11))
{
alert("prime");
}
if(!primeCheck(12))
{
alert("not prime");
}

How to reduce "if statement" conditions? [reduce the conditions inside the if statement]

after days of hard thinking i choose to ask that question. I have if statement with multiple conditions:
//var current is array of arrays of integers
if((current[rot][0] + x)<blocks.length
&& (current[rot][1] + x)<blocks.length
&& (current[rot][2] + x)<blocks.length
&& (current[rot][3] + x)<blocks.length
&& !$(blocks[current[rot][0]+x]).hasClass("blockLand")
&& !$(blocks[current[rot][1]+x]).hasClass("blockLand")
&& !$(blocks[current[rot][2]+x]).hasClass("blockLand")
&& !$(blocks[current[rot][3]+x]).hasClass("blockLand"))
{
//something to happen here ONCE!
}
Because i want something inside to happen just once i think i cant use for loop.
So my question is: is there a possible way to reduce the conditions number? and how?
P.S.: Yes i figured out that i can use flag (true/false) inside and do my stuff outside this if, in another if - but i think that not always gonna work, because for every loop the flag will be different.
var b = true;
for (var i = 0; i <= 3; i++) {
// In two lines for being clear, but it's possible just in one
b = b && (current[rot][i] + x)<blocks.length
b = b && !$(blocks[current[rot][i]+x]).hasClass("blockLand");
// You could speed it up this way.
if(!b) break;
}
if (b) {
//something to happen here ONCE!
}
I think I understand what you are asking but let me know if there is anything else I can do.
JavaScript has a ternary (conditional operator) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator
This operator allows you to assign true/false values based on an internal if/else condition.
Here is some code for you to explain this...
window.onload = function() {
var one = 1;
var two = 2;
console.log(one > two ? "greater" : "not greater");
};
You can also use a Switch statement which you can read about here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch.
Here is an example of a switch statement.
window.onload = function() {
var string = "testing this out";
switch (string) {
case "testing this out":
console.log('testing this out found in condition one');
break;
case "testing":
console.log('found testing');
break;
default:
console.log('not found');
break;
}
};
Let me know if I can improve this.

Call break in nested if statements

I have the following situation:
IF condition THEN
IF condition THEN
sequence 1
ELSE
break //?
ENDIF
ELSE
sequence 3
ENDIF
What is the result of the break statement? Does it break the outer if statement? Because this is what I actually need.
If you label the if statement you can use break.
breakme: if (condition) {
// Do stuff
if (condition2){
// do stuff
} else {
break breakme;
}
// Do more stuff
}
You can even label and break plain blocks.
breakme: {
// Do stuff
if (condition){
// do stuff
} else {
break breakme;
}
// Do more stuff
}
It's not a commonly used pattern though, so might confuse people and possibly won't be optimised by compliers. It might be better to use a function and return, or better arrange the conditions.
( function() {
// Do stuff
if ( condition1 ) {
// Do stuff
} else {
return;
}
// Do other stuff
}() );
no it doesnt. break is for loops, not ifs.
nested if statements are just terrible. If you can avoid them, avoid them. Can you rewrite your code to be something like
if (c1 && c2) {
//sequence 1
} else if (c3 && c2) {
// sequence 3
}
that way you don't need any control logic to 'break out' of the loop.
But there is switch-case :)
switch (true) {
case true:
console.log("Yes, its ture :) Break from the switch-case");
break;
case false:
console.log("Nope, but if the condition was set to false this would be used and then break");
break;
default:
console.log("If all else fails");
break;
}
In the most languages, break does only cancel loops like for, while etc.
To make multiple checking statements more readable (and avoid nested ifs):
var tmp = 'Test[some.email#somewhereouttherebutnothere.com]';
var posStartEmail = undefined;
var posEndEmail = undefined;
var email = undefined;
do {
if (tmp.toLowerCase().substring(0,4) !== 'test') { break; }
posStartEmail = tmp.toLowerCase().substring(4).indexOf('[');
posEndEmail = tmp.toLowerCase().substring(4).indexOf(']');
if (posStartEmail === -1 || posEndEmail === -1) { break; }
email = tmp.substring(posStartEmail+1+4,posEndEmail);
if (email.indexOf('#') === -1) { break; }
// all checks are done - do what you intend to do
alert ('All checks are ok')
break; // the most important break of them all
} while(true);
Javascript will throw an exception if you attempt to use a break; statement inside an if else. It is used mainly for loops. You can "break" out of an if else statement with a condition, which does not make sense to include a "break" statement.
JSFiddle
Actually there is no c3 in the sample code in the original question. So the if would be more properly
if (c1 && c2) {
//sequence 1
} else if (!c1 && !c2) {
// sequence 3
}
I had a similar problem today and found refactoring the conditional logic into a separate function to help.
I find it more readable than the labels and people are more comfortable with return than break. Inline functions are similar but the indentation can get a bit confusing.
In your case it would look like this.
function doThing() {
checkConditions();
// Rest of the code here
}
function checkConditions() {
if (c1) {
if (c2) {
return do1();
else {
return;
}
} else {
return do3();
}
}
Just remove the break. since it is already inside first if it will not execute else. It will exit anyway.
You need that it breaks the outer if statement. Why do you use second else?
IF condition THEN
IF condition THEN
sequence 1
// ELSE sequence 4
// break //?
// ENDIF
ELSE
sequence 3
ENDIF
sequence 4

Categories