Reputation: 599
If I have an if statement that needs to meet these requirements:
if(cave > 0 && training > 0 && mobility > 0 && sleep > 0)
Is there any way to say that all of them are bigger than zero? Just for more efficient DRY code?
Something like:
if(cave, training, mobility, sleep > 0)
Upvotes: 41
Views: 6898
Reputation: 42032
Assuming 32-bit ints.
if ((cave | training | mobility | sleep) > 0)
If any of the above numbers are negative, the result of the OR will be negative and the requirements aren't met.
Edit: that's equivalent to if(cave >= 0 && training >= 0 && mobility >= 0 && sleep >= 0)
and won't when some of the parameters are 0. The fix is to invert the sign bit:
if ((~cave | ~training | ~mobility | ~sleep) <= 0)
Some alternative ways which work even for floating-point values
if (cave*training*mobility*sleep > 0)
if (Math.sign(cave) * Math.sign(training) * Math.sign(mobility) * Math.sign(sleep) > 0)
if (Math.sign(cave) | Math.sign(training) | Math.sign(mobility) | Math.sign(sleep) > 0)
Upvotes: 4
Reputation: 7678
Why you are looking for solution?
Your question looks like best and simple answer, i recommend it. We have multiple solutions for this. Below one is that.
Achieve it by using .every function
var flag = [cave, training, mobility, sleep].every(function(val) {
return val > 0;
});
if(flag) {
alert('All the elements are greater than Zero');
}
Upvotes: 1
Reputation: 3127
As some have stated there is nothing wrong in having multiple simple conditions in an if statement, however I would consider changing the formatting into:
if ( cave > 0
&& training > 0
&& mobility > 0
&& sleep > 0 )
Alternatively I would change the from using these variables as integers, into bool variables, i.e. isCave
, hasTraining
, or similar, and then set the proper bool closer to where your code defines the different properties (Edit: And possibly return early if it is false, to prevent further unneccessary calculations). This would simplify your if statement to the latter in the next code block, which in addition shows a variant which can be used if the conditions becomes slightly more complex or you would like to ease the reading of the if statement:
var isCave = cave > 0; # What does cave > 0 mean?
var hasTraining = training > 0;
var isMobile = mobility > 0;
var isNotSleeping = sleep > 0; # What does sleep > 0 indicate? Unclear
if (isCave && hasTraining && isMobile && isNotSleeping ) {
// Do your thing
}
In other words, the multiple conditions in your if statement is not your biggest code smell, I would shift my focus to giving your variables better names clearly indicating what the value indicates. This would improve reading and understanding of your code, way more than some strange syntax to avoid multiple if conditions.
Upvotes: 29
Reputation: 4516
Filter it with lodash:
var data = [cave, training, mobility, sleep];
var result = _.filter(data, function (datum) { return datum > 0; }).length === data.length;
console.log(result);
It iterates over array elements and returns new array composed of those elements that meet given requirement of being > 0
- if result array is different size than given one it means one or more of it's elements were not > 0
.
I wrote it specifically to check every array value (even if not necessary as first > 0
could give same result) to not stop on first positive as you stated you want to check all of them.
PS You can reverse it to check for <= 0
and check for .length === 0
instaed to be faster.
Upvotes: 2
Reputation: 78595
You could use an array with .every. This is less DRY, but more verbose:
var isGreaterThanZero = function(val) {
return val > 0;
};
if([cave, training, mobility, sleep].every(isGreaterThanZero)) {
// Do Something
}
The reason I like this is that by using an array, it becomes apparent that you're repeating logic for every variable. Naming the callback in an obvious manner helps future readers understand exactly what that check will achieve. And finally, this gives scope for not just numbers, but any check of any type in the future - with any complexity hidden away from the if
statement itself.
Upvotes: 34
Reputation:
There is nothing wrong with having multiple, simple conditions in an if
statement. However, if it cannot fit into a single line (about 80 characters), you have a few solutions.
Ultimately, you are not checking whether four variables are greater than zero. You are checking for a set of conditions. The fact that these conditions are (currently) represented by signed integers is not only irrelevant, but is an implementation details that should be hidden away in functions.
Use intermediary flags:
var valid_location = false;
if (cave > 0 && training > 0)
valid_location = true;
var valid_status = false;
if (mobility > 0 && sleep > 0)
valid_status = true;
if (valid_location && valid_status)
// ...
Use a function:
function can_do_this()
{
// split conditions into logical groups
// checking location, because you need training if you're
// in a cave
if (cave <= 0 || training <= 0)
return false;
// checking status, because you have to be mobile and
// sleepy
if (mobility <= 0 || sleep <= 0)
return false;
return true;
}
if (can_do_this())
// ...
Use functions for the individual conditions you need to check:
function valid_location()
{
return (cave > 0 && training > 0);
}
function valid_status()
{
return (mobility > 0 && sleep > 0);
}
if (valid_location() && valid_status())
// ...
Upvotes: 8
Reputation: 2814
As others have suggested, you can use .every if you don't mind using ES6 or polyfills:
var hasAllStats = [cave, training, mobility, sleep]
.every(function(stat) { return stat > 0; });
if (hasAllStats) { }
Alternatively, you can use .some to get the inverse (Also requires ES6 or polyfill):
var isMissingStats = [cave, training, mobility, sleep]
.some(function(stat) { return stat <= 0; });
if (!isMissingStats) { }
If you don't want to use ES6, you can use reduce:
var hasAllStats = [cave, training, mobility, sleep]
.reduce(function(hasAllStats, stat) {
return hasAllStats && stat > 0;
}, true);
if (hasAllStats) { }
Upvotes: 4
Reputation: 608
You could get the lowest value with Math.min, and then you only need one check against the lower bound.
if(Math.min(cave, training, mobility, sleep) > 0) {
//do something
}
Upvotes: 46
Reputation: 23290
Sounds like a job for a "validator" function like this:
function areAllGreaterThanZero(){
//TODO: check inputs
var result = true;
[].splice.apply(arguments).forEach(function(x){
result = result && (x > 0);
});
return result;
}
if(areAllGreaterThanZero(cave, training, mobility, sleep)) {
// ...
}
Upvotes: 4