I can see there are so many related questions to this. Could not find anything specific addressing my query. Here is my question:
How can i shorten the below if else condition:
If (condition1)
{
If(condition2)
{
Logic A
}
}
Else if (condition3)
{
Logic A
}
One way i could come up was as below:
If (condition1 && condition2 || !condition1 && condition3)
{
Logic A
}
Just wondering if there is a better way of doing it?
In this case optimization is important only from readability point of view. From OP examples I would prefer original one, because it easier to follow for developer/reader who didn't write this code.
We execute one action or do nothing based on conditions, so I would wrap every condition chain which leads to the execution into the method with descriptive name and used them with or operator.
// condition 1 = customer.persisted
// condition 2 = bonuses.has(customer.id)
// condition 3 = promotionCodes.has(customer.promotionCode)
function whenExistingCustomerWithBonus() {
return customer.persisted && bonuses.has(customer.id);
}
function whenGuestCustomerWithPromotionCode() {
return customer.persisted === false && promotionCodes.has(customer.promotionCode);
}
// Usage
if (whenExistingCustomerWithBonus() || whenGuestCustomerWithPromotionCode()) {
// execute logic A
}
you can do this
(condition1 && condition2 || !condition1 && condition3) ? logic(a) : logic(b)
Its called Ternary operator, It would make your code shorter and you can also use it to set a variable, for example
const isTrue = 4 > 3 ? true : false
There are some aspects that you must keep in mind.
It's possible that a shorter code be faster in some script languages (like JavaScript, PHP...).
But it worth? Is your if inside a loop long enough to make any difference in your code execution time?
Do your shortened code makes easier or harder to understand your code? Sometimes joining some if conditions inside a boolean logic makes it easier to understand, but sometimes it's so complicated that is very hard to understand.
sometimes its possible to simplify (note the use of the word 'simplify' instead of 'shorten') conditional logic by reversing it, or by delegating logic to other functions, or a combination of both:
given this:
function performLogic() {
if (condition a) {
if (condition b) {
logic 1
}
} else {
logic 1
}
}
let's try to think about this in reverse:
function performLogic() {
if (!condition a) logic 1
else if (conditoin b) logic 1
}
keep in mind this kind of refactor will not always be possible, and i also advise you to write unit tests for the logic to ensure that the end result remains the same.
It can also sometimes be simplified further depending on the logic in the function. many times we can replace conditional logic with guard clauses like this:
function getSomeValue() {
if (condition a) {
if (condition b) {
... do some logic
return someValue;
}
}
}
this can be changed to
function getSomeValue() {
if (!condition a) return;
if (!condition b) return;
... do some logic
return someValue;
}
Related
What is quicker to process in javascript or NodeJS, else if statements or avoiding them with returns?
Case A
function test(x) {
if (x < 2000) {
return 'output1'
} else if (x > 3450) {
return 'output2'
} else {
return 'output3'
}
}
Case B
function test(x) {
if (x < 2000) {
return 'output1'
}
if (x > 3450) {
return 'output2'
}
return 'output3'
}
I have a gut feeling that case B is quicker with better performance, but just want to confirm with your feedback. Yes, I'm aware the difference is tiny and it would be merely a micro-optimization, but what is faster, case A or B?
An else is always implied when you have an if (because the compiler should know where to jump when the condition is not met. This "where" part is the implied else). There are no scopes in the produced compiled code. There are only instructions one after another. Some of them are labeled so they can be the target of a jump.
I am pretty sure that the output of both code samples is exactly the same. In pseudoassembly it would be something like
[check-equal] $x, 12142 // check equality
[goto-if-zero] :label1 // Conditional jump to label1 position in case previous check was false
[set-retval] 'output1' // setting return value
[goto] :end // unconditional jump to the end of funtion
label1: [check-equal] $x, 798789 // check equality
[goto-if-zero] :label2 // Conditional jump to label2 position in case previous check was false
[set-retval] 'output2' // setting return value
[goto] end // unconditional jump to the end of funtion
label2: [setretval] 'output3' // setting return value
end: [return] // returing
Thank you guys for citing me the Javascript benchmark which I was not aware of. Well, I made some tests and contrary to my gut feeling, case A is slightly faster or I can say that the difference is neglectable because the difference is within the error margins.
test suites here:
https://jsbench.me/mqka3oap2y/1
https://jsperf.com/else-if-or-avoid-with-return/1
using this code
for (var i=0; i<10000; i++) {
test(i)
}
Case A: 140,931 ops/s ±1.03%
Case B: 140,147 ops/s ±1.12%
I have some functionality dependent on many conditions. All variables in conditional statements are boolean variables and the code is the following and I don't like it:
if (userHasMoreThanOneMarket && isOnlyMarketSelected || !userHasMoreThanOneMarket && userHasMoreThanOneAgency) {
if (isOnlyAgencySelected) {
//do case 1
} else if (noAgencySelected && isOnlyMarketSelected) {
//do case 2
}
}
Is there a way to make it more understandable and nice?
That's about as concise as you're going to get with JavaScript. I suppose if you really wanted to, you could create variables to store your binary options:
var multiMarketOneSelected = userHasMoreThanOneMarket && isOnlyMarketSelected;
var singleMarketMultiAgency = !userHasMoreThanOneMarket && userHasMoreThanOneAgency;
if (multiMarketOneSelected || singleMarketMultiAgency) {
if (isOnlyAgencySelected) {
//do case 1
} else if (noAgencySelected && isOnlyMarketSelected) {
//do case 2
}
}
Though I don't really know if you gain much readability from that.
Your code seems fine, but if you don't like it you could do something like this (note that the only improvement here is style, if you like it better):
function check(){
return {
valid: userHasMoreThanOneMarket && isOnlyMarketSelected || !userHasMoreThanOneMarket && userHasMoreThanOneAgency,
case: [
isOnlyAgencySelected,
noAgencySelected && isOnlyMarketSelected
]
};
}
var conditions = check();
if (conditions.valid) {
if (conditions.case[0]) {
//do case 1
} else if (conditions.case[1]) {
//do case 2
}
}
Some things I would try to make the code more readable:
Initialise the variables in a way that you don't have to negate them again. So !userHasMoreThanOneMarket becomes userHasOneMarket
isOnlyMarketSelected sounds redundant to me. And you are checking it in the outer if-clause and the inner again.
You probably have a lot of code above this code snippet to initialise and set all this boolean values. Try return; statements after each variable to get rid of if-conditions.
I hope this helps.
I want to exit from the below if block in Javascript. if I return, then it does not check for the next if condition. How do I do that?
if ($('#id1').length > 0) {
if(yester_energy == "NaN" || yester_energy == 0){
//break from #id1
}
else{
//something
}
$("#abc").html(somthing)
}
if ($('#id2').length > 0) {
if(yester_energy == "NaN" || yester_energy == 0){
//break from #id2
}
else{
//something
}
}
Super late to the party, but for folks from search, you can use something called labeling. It's not good practice, but in rare cases that can be applied. Basically you can assign a name to the if statement that you want to break from. And anywhere in statement call break from specified name.
Code example:
my_if: if (condition) {
// do stuff
break my_if;
// not do stuff
}
in your particular case:
id1: if ($('#id1').length > 0) {
if(yester_energy == "NaN" || yester_energy == 0){
break id1;
}else{
//something
}
$("#abc").html(somthing)
}
More about labeling can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label#Syntax
Even later to the party... Typically in such situations, I use a combination of if and do...while as follows...
if ( condition ) do {
// processing
if ( exit_condition ) break;
// more processing...
} while ( false );
Thus, when the break is encountered, it applies to the do...while loop, and processing continues after the while, effectively breaking out of the outer if statement...
All your code after if(isNaN(yester_energy) || yester_energy == 0) is in else block, so it'll not be executed if your data matches this if. And you just don't need anything else.
Also, if you want to check if variable got NaN value, then use isNaN() function. You can't just compare it.
Use switch statment,
switch(n)
{
case 1:
execute code block 1
break;
case 2:
execute code block 2
break;
default:
code to be executed if n is different from case 1 and 2
}
you can use function and pass command
function iff(condition){
if(condition ==0) return;
console.log("other commands")
}
iff(0);
iff(1)
Don't Use Labeling
You can do labeling as the other answer suggests, but it smells odds and it will definitely come up in code review. It will confuse readers of your code and increase the maintenance burden of your codebase.
Answer
Best is to refactor (extract out) the code inside the if-statement into a separate function that you can then return from. In addition to allowing you to exit from the code block early, it also makes your code more modular and readable.
Example (based on OP)
if ($('#id1').length > 0) {
ifInner(yester_energy)
$("#abc").html(somthing) // [sic]
}
if ($('#id2').length > 0) {
ifInner(yester_energy)
}
// Rename to something more descriptive.
function ifInner(yester_energy) {
if (yester_energy == "NaN" || yester_energy == 0){
// Break out.
return;
}
else {
// something
}
}
Adding another answer to the pool, in many cases using a try catch makes perfect sense:
if(something is allowed) {
try {
if(missing requirements) throw 'missing requirements'
//do your stuff;
}
catch {
//you may do logging and issue warning here
}
}
Why I am asking
I have been having a lot of trouble understanding the shorthand for the if sentence in JavaScript, and I haven't found an article or tutorial that described it well. And that's why I am stuck opitimizing my little code. And I am new to JavaScript, so if someone could give me a basic understanding of the shortning of this code, I would very much appreciate you telling me the magic behind the code.
What I need help with
I am going to use the exact same code in a lot of functions. Therefore, I want to optimize it and make it shorter version of the code.
function welcomemessage() {
if (br == 1) {
hello();
}
else {
hey();
}
}
Use the ternary operator.
function welcomemessage() {
(br == 1) ? hello() : hey();
}
The ternary operator is useful, and not difficult to understand. here's how it works.
(condition) ? (true) : (false)
Edit:
Since JS treats functions as first class objects, it is possible to create a wrapper. Something like below (not tested though)
function ternaryWrapper(br, functionTrue, functionFalse){
return (br == 1) ? functionTrue : functionFalse;
}
//call it
ternaryWrapper(2,hello, hey);
Even shorter:
function welcomemessage(br){
[hello,hey][br-1](); //This will work.
}
welcomemessage(1); //hello();
welcomemessage(2); //hey();
Fun Fact:1
To make your script hard to read for someone else, do it like this:
function welcomemessage(){
return br==1 && (hello(),1) || (hey(),1); //This will work too.
}
1 Totally not related to the answer.
Update
var something = ( (br == 1) ? hello() : hey() );
something will be the value hello() or hey() returned.
Or:
var msgfuncs = [ hey, hello ];
function welcommessage() { msgfuncs[br](); }
(assumes that when "br" isn't 1 it's 0, which of course may be an invalid assumption.)
If the choice is made with different functions, just put the array directly in the surrounding function:
function welcomemessage() {
[ hey, hello ][br]();
}
If you want to make the decision and save the function to call later, you can do this:
var messageFunction = [ hey, hello ][ br ];
then any time later:
messageFunction();
In case br is always be numeric, the xbonez answer can be optimized a little bit by using strict comparison === (because it is a little bit faster):
function welcomemessage() {
(br === 1) ? hello() : hey();
}
And another interesting option is:
function welcomemessage() {
(br - 1) ? hey() : hello();
}
This last function works because when br is 1, it will turn to 0 (which is a falsish value) and evaluate to false, triggering hello(), and for the rest it will trigger hey()
Say I've got this loop
while(condition1 && condition2 && condition3 && condition4){
browseReddit();
}
if (!condition1){}
if (!condition2){}
if (!condition3){}
if (!condition4){}
It could be broken by any of the 4 conditions becoming false, and I would want to execute different code based on which one(s) it was. Ideally, I would not like to evaluate them all more than I absolutely have to. Assume browseReddit() forces us to evaluate them all again.
Putting an if chain after the loop is how I'm doing it currently. Is there a cleaner way? value brevity above all else in your answer.
while (1) {
stop = 0;
if (!condition1) {
// condition 1 code
stop = 1;
}
if (!condition2) {
// condition 2 code
stop = 1;
}
if (!condition3) {
// condition 3 code
stop = 1;
}
if (!condition4) {
// condition 4 code
stop = 1;
}
if (stop) {
break;
}
browseReddit();
}
Final edit:
while((condition1||function(){alert("condition1 failed!");}()) &
(condition2||function(){alert("condition2 failed!");}()) &
(condition3||function(){alert("condition3 failed!");}()) &
(condition4||function(){alert("condition4 failed!");}())){
browseReddit();
}
jsfiddle: http://jsfiddle.net/ctrlfrk/HjftT/3/
I would go with the way you have in your current code sample, so that you don't exempt yourself from testing all four of your exit cases.