Say I have a random number.
Which is more efficient:
if (num == 1) {
} else if (num ==2) {
} else if (num == 3) {
} else if (num == 4) {
} else if (num == 5) {
} else {};
or
if (num == 1) {};
if (num == 2) {};
if (num == 3) {};
if (num == 4) {};
if (num == 5) {};
is there much of a different performance-wise?
Or should I do a switch chain?
If you have a small number of situations that you want to handle separately (and you are using a number to differentiate), then the Switch statement would provide clearer logic to someone (including you) who tries to read or modify your code.
If / else if chains may be mis-perceived later
Successive If statements mean you are constantly checking for a situation you know is wrong
A bit late to the party, but apart from the other valid answers:
what if you could call your intended subcode (almost) directly (if you have a LOT of options)....
I have a different solution (you were open other options):
var switchArr=[ //skipping 0
, function(){ /* do stuff for 1 */ }
, function(){ /* do stuff for 2 */ }
, function(){ /* do stuff for 3 */ }
]; // you could also set them directly if you have irregular (large) intervals
if(switchArr[num]){
switchArr[num]();
} else {
//defaults
}
EDIT: alternatively (expanding on the above concept) using an object (because order does not have to be guaranteed, as array does) and some closure and a simple way to pass num to the handler function:
var switcher=(function(){
var N, F={
default: function(){ alert('default function for '+N); }
, 1: function(){ alert('doing stuff for '+N); }
, 2: function(){ alert('other stuff for '+N); }
, 5: function(){ alert('I am function '+N); }
};
return function(n){ F[N=n] ? F[n]() : F.default(); };
})();
num=3; switcher(num); // default function for 3
num=5; switcher(num); // I am function 5
Depending on use-case one of the above (or a hybrid) could be a better solution. If execution-time is at a prime, don't use the helper-function (that does the check) since that saves a function-call.
EDIT 2:
In the comments is asked for the benefit of this alternative:
Contrary to popular belief (that javascript/ecmascript uses a switch to 'directly jump' to a start-point in a codeblock), the switch statement in modern browsers evaluates the case expressions using the === strict comparison operator (so the expressions must match without any type conversion) in the order in which they (case not default) appear until it finds a value that matches (after which it will 'fall through' until a break or a return when inside a function is encountered or the codeblock ends, hence default can appear anywhere in the codeblock, not only at the end).
This is because the ECMAScript v3 standard allows each case to be followed by an arbitrary expression.
Note (for older browsers) that the switch statement is implemented in JavaScript 1.2, but it does not fully conform to the ECMAScript specification. In JavaScript 1.2, case expressions must be literals or compile-time constants that do not involve any variables or method calls. Furthermore, although ECMAScript allows the switch and case expressions to be of any type, JavaScript 1.2 and JavaScript 1.3 require that the expressions evaluate to primitive numbers, strings, or boolean values.
Source: JavaScript: The Definitive Guide (4th ed)
See the resemblance with an if-chain? The difference is the ability to fall through (until end/break/return).
The amount of comparison work (in an example where you have a LOT of different cases) is thus the same (at least, per spec, not guarantied per interpreter implementation, which wildly varies among versions).
A lot of (generally not frowned upon) optimization involves tweaking code to have a predictable relatively scalable (in regard to the host's capability's) execution-time. In my suggestion (intended to show ways of thinking outsize of the box), you have a small fixed number of steps before your payload executes (something that you can guarantee according to the language-spec).
That leaves 'understandability' which is a tricky question because that is highly related to 'intent' and 'readability', thus opening the can of worms regarding different viewpoints/options/mantra's/best-practices, much of which hold different value (or plain simply don't/shouldn't apply) to 'javascript' (for web-based applications) (in my opinion).
There can be thought of many different approaches using comments etc (or the second example that uses an object) and different coding-styles/patterns that would alleviate initially perceived hindrance of 'clear code'.
After-all, ideally one should have good documented 'raw' ((gzip-)pre-optimized where applicable (you don't want to maintain/debug both raw and 'compiled' code)) code, but send minified (without doc/comments minified var-names etc) code to the browser (in production).
Finally as to performance, again depending on what one is trying to do (and lot of cases are involved), the array version (without helper function) will be smallest and fastest for a range of numerical cases. The object then has its strength in (irregular) numerical intervals and string-based switches. However, as always, one must test (supported target-)hosts/browsers to assess their performance. However up to now, in my experience when dealing with a lot of cases, this one is a winner.
Final note, when dealing for instance with a known set of cases, one wouldn't even need to check if the case exists, let alone need a helper function.. speed for the win (in such a case).
Generally else-if has better performance than if chain. But to use switch case in such a case would be the best choice.
The efficient way to check is switch statement rather than if,
switch(num) {
case 1:
do something;
break;
case 2:
do something;
break;
default:
default do something;
}
The better approach especially for big codes is an if else statement(or even better case).
Using multiple if statements leads the pc to do unnecessary calculations.
For example:
if (5 > 3){
alert("True");
}
else{
alert("False");
}
This is a boolean expression.In the above example the cpu checks the if(5 > 3) which returns true and stops(It won't execute or check the else).
The same but using multiple if
if (5 > 3){
alert("True");
}
if (5 < 3){
alert("False")}
It will do the same as the previous code but now it will execute 2 calculations instead of one
Related
This may be a dumb question but what is an easy way to write a clean condition statement, for example lets say if I have a conditional statement where I only want it to happen before a block of code if it meets the requirement and if it doesn't then I want it to happen after the block of code. But it must happen in that order
EDIT
This code is NOT broken.. I was simply asking if there was a better way of structuring this conditional statement and I found out that putting the //random code in a helper method and combining the two if's into an else if would solve it. See my answer below.
if(number === 250){
// sameMethod()
}
//random code
if(number !== 250){
// sameMethod()
}
Solution
function helper() {
//random code
}
if(number !== 250){
helper()
// same code
} else {
// same code
helper()
}
if(number == 250){
// sameMethod()
}
//random code
if(number != 250){
// sameMethod()
}
For this, and based on the information at hand, I would recommend keeping the code as is. The way you have written this code, an if-else block would have a serious impact on the flow of your application.
Assume that randomCode is a method call, which performs the next operation:
function randomCode() {
this.number += 5;
}
and you start the code with the state of your application having the value of number as 245.
if ( number == 250 ) { // conditions 245 == 250 evaluates to false
// sameMethod -> will not be executed
}
randomCode(); // increases the value of number with 5
if ( number != 250 ) { // condition 250 != 250 evaluates to false
// sameMethod -> will not be executed
}
Just slapping an if-else, like this:
if ( number == 250 ) { // condition 245 == 250 evaluates to false
// sameMethod
} else {
randomCode();
// sameMethod -> here it will be executed, even though number now is 250. Change in behaviour
}
So, there are two things to consider: either the example code you posted was the correct flow, making it correct (but might end up in executing sameMethod twice, or not at all, since the value of number could be altered in the randomCode part, or both sameMethod and randomCode have to be executed (exactly) once, depending on that condition.
If so, the original (pseudo?) code was faultive, but the result would indeed come to:
if ( number == 250 ) {
sameMethod();
randomCode();
} else {
randomCode();
sameMethod();
}
This is where monads and all that jazz show their ugly mugs.
Assuming you are talking about java, you could for example write a runSequentially method that results in letting you write:
runSequentially(() -> sameMethod(), () -> {
// random code
}, number != 250);
Where runSequentially will first run the first Runnable, then the second Runnable - unless the condition is false, in which case it runs the second, then the first.
In java, this is not, however, local mutable variable, checked exception, and control flow transparent which are sufficient downsides that I'm not sure this is a good idea. Especially considering that apparently execution order matters which usually suggests mutating state. But, if you insist, it'd be something like:
public static void runSequentially(Runnable a, Runnable b, boolean flipOrder) {
if (flipOrder) { b.run(); a.run(); }
else { a.run(); b.run(); }
}
Javascript is a lot more laissez-faire (and a totally different language; did you tag it because perhaps you were unaware that 'java' and 'javascript' are completely unrelated? It's a common mistake - in that case, disregard this bit), and doesn't suffer from the transparency issues as much. Javascript has no checked exceptions, javascript lets you mutate outer state (there are some WTFs in javascript-the-language about this, but that's a separate issue). The biggest issue is control flow (you can't as easily break/continue loops in the 'outer' code from within these closures).
Going back to java for a moment, using lambdas (closures) in contexts where:
The lambda is run 'in-line', that is, you pass the lambda to some method, and once that method returns, the lambda is 'forgotten about' by said method: That method did not store the lambda in a field, did not pass it to another thread, did not pass it to other code that is going to store it in a field or pass it to another thread).
The code in the lambda is not designed 'functional style' (e.g. it mutates state or does a bunch of I/O), then
you're probably messing up. Lambdas really suck in that environment, those transparency issues are grating then. Note that if the lambda does 'travel' (is stored / moved to another thread), that lack of transparency is in fact a great thing because those 3 'transparencies' become bizarre braintwisters - best to just not allow them.
That's why I recommend against this, if you're writing java. But now you know how one would.
Thanks for all the advice, I should've been more clear about the language since I thought this was a fairly simple solution that might work in both Java and Javascript. I ended up just putting the "random code" in a helper function.
function helper() {
//random code
}
if(number !== 250){
helper()
// same code
} else {
// same code
helper()
}
Basically the idea was that, the order of which block of code that gets executed mattered depending on a fixed variable. It was messy without a helper function due to duplicated code so this simple solution fixed it. Let me know if you guys think of a more clever way! Thanks
So, I am geocoding addresses from the Google Places API. There are 38 Google address component types, and we have ~5 in-house address component types, so I need a system of mapping a number of Google types to our in-house types, with fallbacks.
For example:
var neighbourhood = googleResponse.neighborhood || googleResponse.sublocality_level_2 || googleResponse.sublocality_level_1
What is the best/cleanest/most efficient way to do this? Basically, I need to assign a var to some returned value, unless that returned value is undefined, and then move down the chain.
I think your approach is sound - using the short-circuiting ORs feels a lot cleaner than having some sort of branching statement to me. My two recommendations would be:
You should probably add some kind of hard-coded value (an empty string, perhaps? Depends on your use case) as a final fallback, so that if all of the options aren't found, you don't end up with the variable being set to something unexpected. I think being 100% explicit about all the possible things that could be returned is always a good practice.
I'd recommend pulling that logic out into a function, so that if you want to reuse it elsewhere it'll be more maintainable. Even if you don't think you'll need to use it again, it's still worth doing in case you change your mind later on - having to go through and replace every instance of a piece of code is incredibly tedious! It also makes your code a lot easier to test - you can pass in a hard-coded googleResponse and check that the output matches your expectations.
So my approach would probably look something like this:
function getNeighborhood(googleResponse) {
return googleResponse.neighborhood
|| googleResponse.sublocality_level_2
|| googleResponse.sublocality_level_1
|| "";
}
var neighborhood = getNeighborhood(googleResponse);
EDIT:
In response to your comment, there's a couple of options I can think of for values that have to be concatenated.
If it's just a matter of "everything or nothing", you could write this quite elegantly with a ternary expression:
function getStreet(googleResponse) {
return googleResponse.street_number && googleResponse.route
? googleResponse.street_number + googleResponse.route
: "";
}
However, if you start trying to nest these with fallbacks, it's going to get very unreadable very fast. At that point, you're better off just relying on a if/else if/else - it's a bit long winded, but it's comprehensible, and that's more important in my eyes.
function getStreet(googleResponse) {
if (googleResponse.street_number && googleResponse.route) {
return googleResponse.street_number + googleResponse.route;
}
else if (/* fallback */) {
return /* concat here */;
}
else {
// Make sure to always return a value, even if all of
// the other fallbacks fail!
return "";
}
}
Good evening/morning (depending of your place),
I'm a newbie 'developer' (JS/Meteor platform), and every day I discover a new thing about JS. Knowing my low level, It is not that hard...
I'm currently wondering the best way/practice to code a switch(true).
More precisely I have a Switch statement with something like 20 cases.
Currently, I decide not to nest some cases together, I find it less easy to read. So my statement looks like something like this:
switch()
case 1
case 2
case 3
case 4
case 5
case 6
...
default
Instead of something like:
switch()
case 1
if
elseif
else
//or
case 2
switch()
case 2.1
case 2.2
My question is: each case tests something like 5+ functions. So a case is basically written this way:
case ( function1()
&& function2()
&& function3() == null
&& typeof abc[1] === 'undefined'
&& function4() === 'xyz') : //etc...
Is there a better way to chain functions?
I'm currently looking at chaining method in a jQuery way: function().function2().function3()... But I don't know if it exits a better way to deal with this kind of situation.
I will be delighted to get your feedback/advice and any reading/lecture you would recommend. I also hope this question is "right" for SO.
Thank you very much.
You shall always strive against small functions to increase readability. It might be a good idea to group function calls in new functions. The faster you can determine what a function does the better. Try to only have things relevant to the current function, for example:
You are supposed to fetch a lot of information about a person but the information is spread into different sources forcing you to have one function for name, one for age, one for shoe size and so on.
Instead of writing it like
case 1:
var person = {
name: getName(),
age: getAge(),
showSize: getShowSize()
};
You could write it like
case 1:
var person = getPerson();
And the the getPerson function
function getPerson() {
return {
name: getName(),
age: getAge(),
showSize: getShowSize()
}
}
In your 20 cases I'm sure there are logical groups of functions that is used in several cases. Try to group them together if they have any logical connections. With a switch as large as with 20 cases I would try to not write to much code in every case since it would probably make it difficult to see what the function does.
I hope I got your problem and at least gave you some advices you find useful.
I am writing a Safari extension, and would like to detect what page (url) I am currently on, and do things accordingly.
Right now my code looks something like:
if (linkHas("facebook.com")) {...}
else if (linkHas("google.com")) {...}
else if (linkHas("yahoo.com")) {...}
where linkHas() is a function that basically returns 1 if it has the parameter, and 0 otherwise.
Is it possible to write this one single switch statement? I've read somewhere that switch statements are implemented as hash tables if there are more than 5 options. For a small script like mine, the speed probably doesn't really matter much here, I'm really just trying it as an exercise.
The simple, and straight answer is no.
The switch expression has to be/return a value, that is evaluated against the value of each case. As JCOC611 has actually demonstrated, it can be done, but I beg you, don't :)
There is probably definitely a better way of implementing what you're after, but that wasn't your question, so I'll leave it at that.
EDIT
In fact, let me show you a better way.
function doFacebookStuff() {
console.log('Hello Facebook!');
}
function doGoogleStuff() {
console.log('Hello Google!');
}
function doYahooStuff() {
console.log('Hello Yahoo!');
}
var domainActions = {
'facebook.com': doFacebookStuff,
'google.com': doGoogleStuff,
'yahoo.com': doYahooStuff
}
var matched = Object.keys(domainActions).filter(function(domain) {
if (linkHas(domain)) {
domainActions[domain]();
return true;
}
});
console.log('matched domains:', matched);
You can also replace .filter() with .some(), to have it stop at the first match it finds.
Edit: Disclaimer: the following is something you should not do, but is there for reference purposes only. Don't let people tell you you can't, but listen when they say you shouldn't.
The very naive way:
switch(true){
case linkHas("facebook.com"):
// ...
break;
case linkHas("google.com"):
// ...
break;
case linkHas("yahoo.com"):
// ...
break;
}
This has absolutely no performance benefits though. In fact, it might be slower if all the functions are evaluated before the equality tests are performed.
The long way would be to refactor linkHas to be getLinkDomain and check on whatever that returns.
In fact, lets do that. Using the convenient function extractDomain, written by lewdev, you can:
var domain = extractDomain(link);
switch(domain){
case "facebook.com":
// ...
break;
//...
}
Create an "enumeration" of domains to avoid magic strings.
Create a function "getDomain" that returns one of said enumeration.
Create your own hash table called "actions" using an object literal, keyed on said enumeration values. Hash table values can be functions containing the logic to run for that key.
Then write:
actions[getDomain()]();
This question already has answers here:
Using 'return' instead of 'else' in JavaScript
(13 answers)
Closed 5 years ago.
In the following example - given that the return value isn't of any importance - is there a reason to prefer either method over the other?
// Method 1
function (a, b) {
if (a == b){
// I'm just interested in
// the stuff happening here
} else {
// or here
}
return true;
}
// Method 2
function (a, b) {
if (a == b){
// I'm just interested in
// the stuff happening here
return true;
}
// or here
return true;
}
It seems that best practices (mostly by places I've worked for) is to set default values at the top of a method or function and only change those values if some condition occurs. Thus, the use of else is not needed so Method 2 is preferred.
Since the example is JavaScript, special attention needs to be paid in regards to code size. So Method 2 would create less code for the same functionality, furthering its argument as the preferred.
However, if you have more than 2 possible conditions, an else or else if cannot be avoided. However, most places I've worked prefer a Switch Case in these situations.
I would prefer Method 1 because it is less confusing to read. Also, less duplicate code.
I would base my decision on clarity of code and readability, i.e.:
Choose method 1 when you need to do more stuff in the block after the if-block.
Choose method 2 when you only need two blocks of code, it's then clearer to read
Choose method 1 again in cases where you explicitly think your readers wouldn't understand your cryptic code without the word "else"; this is common when the blocks become larger than a few lines.
Many of today's programmers consider less indentation easier to read and I agree. In which case general preference should go to using the second method.
I would recommend method 1 as it is more readable and self documented.
Any modern browser's interpreter should eliminate any performance advantage in either direction.
There are a couple of reasons method 1 is preferable that haven't been mentioned yet. Having a single point of exit makes any future modifications that require an action common to both branches easier and less likely to be buggy (because the author missed the early return. Similarly, in some cases it makes debugging easier, by providing a common place to put a breakpoint or alert().
Readability here really depends on the role of the function.
If this function will ALWAYS return true, then I would prefer the Method 1 It is clear because it only returns in one place, and it is easy to see it will always be true.
In the above case, Method 2 is more confusing. It returns in multiple places, and is more confusing thusly. Consider a developer unnecessarily traversing possible branches and then seeing how they affect the return value. In this simple case, it is not as big of a deal, but when you get more elaborate conditionals, I would really avoid this approach.
I would only use Method 2 if you have very little code in the if block. Such as something that would deal with an edge case.
Hope that helps.