Can this positive / negative check be simplified? - javascript

I basically want to check if newValue goes past targetValue. But targetValue could be either a positive or negative number, so if ( newValue < targetValue ) won't necessarily work.
I coded it the way below, and I may be overthinking things here but I wondered if there's a way to rewrite the if-check a bit more elegantly…
var newValue = 0;
function ChangeValue ( targetValue : int )
{
var isTargetPositive = ( targetValue > 0 );
if ( isTargetPositive && newValue < targetValue || !isTargetPositive && newValue > targetValue )
newValue = math.moveTowards( newValue, targetValue, 1 );
else
// Do something else
}

The only thing I can think of that keeps your conditions exactly as they are is removing the isTargetPositive variable and replacing your if statement with the following:
if ( targetValue > 0 ? newValue < targetValue : newValue > targetValue )

this is almost the same case as in my chess project where I changed:
if((obj.ActiveColor&&current_val>0) || (!obj.ActiveColor&&current_val<0)){}
with
var impossible_to_name = (current_val * (obj.ActiveColor?1:-1));
if(impossible_to_name>0){}
I know you don't need to cache the var, but in my case I was going to use it later so I cached it, my code is so complex that I couldn't even give a proper name to my var, I am also not entirely sure if this will help you, if I couldn't translate it into your code, chances are you can't neither but I will try to understand my code again and make an edit to my answer.
Note: my code was wrapped in if(current_val){...} so the value is anything except 0

var newValue = 0;
function ChangeValue ( targetValue )
{
if (
((targetValue > 0) && (newValue < targetValue))
||
((targetValue < 0) && (newValue > targetValue ))
)
{
newValue = math.moveTowards( newValue, targetValue, 1 );
}
else{
// Do something else
}
}

You can always make a subfunction if this is not clear enough
function abs_compare(target, number) {
return target != 0 && ((target > 0 && target > number) || target < number);
}
if (abs_higher(targetValue, newValue)) {
newValue = math.moveTowards(newValue, targetValue, 1);
}
I would also prefer target != 0 rather than double checking if it is superior or inferior to 0 because it is more clear in your condition statement that it is a forbidden value.
Also, Pointy said that since you have initialized newValue to 0, it will always remains to 0 which is currently false since ChangeValue is a function. The newValue can be changed before the function call.
UPDATE
I may have read too fast. Comparing target to 0 won't keep your actual logic and it is the same as the double check. Anyway, you can still use a function.
Also the best answer would rather be using the condition target > 0 ? target > number : target < number

Test (input: 5)
isTargetPositive - matched
newValue < targetValue - matched
Test (input: -1)
!isTargetPositive - matched
newValue > targetValue - matched
+ve or -ve integer, it will match the IF.
isTargetPositive && newValue < targetValue, same right? Why use &&?
I think one condition is enough.

Related

how can I make this func inside a for loop work?

Originally I had this block of code...
//focusOn.value => inpout index
const nextInput = (): void => {
if (
focusOn.value !== null &&
focusOn.value < props.length - 1 &&
) {
inputs[focusOn.value + 1].focus()
}
}
What's doing that function? ⇒ focusOn.value = index
code is a reactive object[] and inputs is an Array too.
You can see it in the vueDevtools from this img:
The issue I'm having is that if you type really fast, there's a possibility that an input get jumped and stays with no value.
So naturally I thought, iterate the code Reactive object which holds the values and make a conditional.
My first attempt was this:
//focusOn.value => inpout index
const nextInput = (): void => {
for (let i = 0; i < code.length; i++) {
console.log(code[i])
console.log(code)
if (
focusOn.value !== null &&
focusOn.value < props.length - 1 &&
code[i] !== ' ' &&
code[i] !== undefined
) {
inputs[focusOn.value + 1].focus()
}
}
}
With the for() in that position, I ended up executing the function 4
times, each one for every input ⇒ That's why, as you can see in the
IMG ⇒ instant jump to the last one.
So now I though well… I should make the for() outside the function but the problem I have right now is, how do I execute the function, I mean, it's kind of a closure, the function leaves in the for lexical scope. And that's the problem that I'm facing. How should I proceed to solve this issue?
Here's my last attempt in which I make the for wrap around the function:
//focusOn.value => inpout index
for (let i = 0; i < code.length; i++) {
const nextInput = (): void => {
// for (const element of code)
console.log(code)
console.log(focusOn.value)
if (
focusOn.value !== null &&
focusOn.value < props.length - 1 &&
code[i] !== ' ' &&
code[i] !== null
) {
inputs[focusOn.value + 1].focus()
}
}
}

console.log(-1) still returns NaN

I have my js code for homework here. I have an if statement that should return -1 in console when the input is not a number but instead of returning -1 it returns NaN. Can anybody help me with this?
function calculateFoodOrder(numAnimals, avgFood) {
// IMPLEMENT THIS FUNCTION!
var total = avgFood*numAnimals;
if ((Number(numAnimals || avgFood) < 0) && (isNaN(numAnimals || avgFood))) {
console.log(-1);
} else {
return total
}
}
calculateFoodOrder()
Default values in your function are 'undefined'. That's why javascript is showing NaN. Define default values to avoid this. For example:
function calculateFoodOrder(numAnimals = 0, avgFood = 0) {
var total = avgFood*numAnimals;
if ((Number(numAnimals || avgFood) < 0) && (isNaN(numAnimals || avgFood))) {
console.log(-1);
} else {
return total;
}
}
If I understand your task correctly, you merely have to check both parameters for not being NaN using isNaN.
Your sample code does not work because any comparison with NaN returns false and thus Number(numAnimals || avgFood) < 0 is never going to be true. Check here for details on NaN.
function calculateFoodOrder(numAnimals, avgFood){
//REM: Default result
let tResult = -1;
//REM: Check if both paramters are not NaN
//REM: Be aware that whitespaces and empty strings validate to zero
if(
!isNaN(numAnimals) &&
!isNaN(avgFood)
){
tResult = Number(avgFood) * Number(numAnimals)
};
return tResult
};
//REM: Default test case
console.log(calculateFoodOrder());
;document.querySelector('button').onclick = function(){
console.log(
calculateFoodOrder(
document.getElementById('innumAnimals').value,
document.getElementById('inavgFood').value
)
)
};
<input type = 'text' value = '' id = 'innumAnimals' placeholder = 'numAnimals' />
<input type = 'text' value = '' id = 'inavgFood' placeholder = 'avgFood' />
<button>do</button>
Please do not confuse yourself with caveats if you are a beginner. You should assign to itself after converting to number, then judge if it's a NaN value or less then zero just like this,
function calculateFoodOrder(numAnimals, avgFood) {
// IMPLEMENT THIS FUNCTION!
numAnimals = Number(numAnimals);
avgFood = Number(avgFood);
var total = avgFood * numAnimals;
if (isNaN(numAnimals) || isNaN(avgFood) || numAnimals < 0 || avgFood < 0 ) {
console.log(-1);
} else {
return total
}
}
calculateFoodOrder()

Which is right way to use below statement performance wise?

Which approach is most recommended. First or Second ?
var x = document.querySelectorAll("span");
// #1: Console returns false
x.length > 0 && x[0].blur();
// #2: Console returns undefined
if (x.length > 0) {
x[0].blur();
}
If you find x.length > 0 then you will definitely get x[0] and do not need to check && x[0].blur();. So your second approach is much better.
if (x.length > 0) {
x[0].blur();
}

How to catch null, undefined, blank values with AngularJS filter

I'm attempting to write a filter for use in a grid that will catch all null, undefined, blank string, or other similar values and display a dash "-". I've written the following so far, but it doesn't catch null values, and I'm wondering if it could be more succinct and possibly refactored to avoid three layers of nested if/else statements. Percentage values need to be checked that they're over 0 and under 1. Also, negative numbers and 0's should be returned as is. Thanks!
angular.module('AdverseEventsExplorer.main').filter('emptyCellFilter', function ($filter) {
return function (input, cellFilter, args1, args2) {
if (cellFilter == undefined) {
return (angular.isNumber(input) || angular.isDefined(input) && input.length > 0) ? input : '-';
} else {
if (cellFilter.match(/pctg|percent|pctgFilter|incidence/ig)) {
return (input > 0 && input < 1.0000000) ? $filter(cellFilter)(input, args1, args2) : '-';
} else {
return (angular.isNumber(input) || angular.isDefined(input) && input.length > 0) ? input : '-';
}
}
};
});
Version 2.0 taking into account #tymeJV's comment:
angular.module('AdverseEventsExplorer.main').filter('emptyCellFilter', function ($filter) {
return function (input, cellFilter, args1, args2) {
if (!cellFilter) {
return (angular.isNumber(input) || (input)) ? input : '-';
} else {
if (cellFilter.match(/pctg|percent|pctgFilter|incidence/ig)) {
return (input > 0 && input < 1.0000000) ? $filter(cellFilter)(input, args1, args2) : '-';
} else {
return (angular.isNumber(input) || (input)) ? $filter(cellFilter)(input, args1, args2) : '-';
}
}
};
});
Whenever you encounter a function that's getting too complex to refactor try extracting some of the smaller statements to concisely named variables. It makes it much easier for our brains to keep track of the function's requirements, and it's also more readable to new devs reading your code.
var inputHasValue = angular.isNumber(input) || input;
if(!inputHasValue){
return '-';
}
if (!cellFilter) {
return input;
}
var isPercentageCell = cellFilter.match(/pctg|percent|pctgFilter|incidence/ig);
var valueIsInRange = input > 0 && input < 1;
if(!isPercentageCell || valueIsInRange){
return $filter(cellFilter)(input, args1, args2);
}
return '-';
typeof x ==='number' || !!x
is false when x is null, undefined or empty string
Only one case in which it doesn't work – if you need to filter boolean variables, but your case doesn't seem to need it.
Anyway in that case you can use
typeof x === 'boolean' || typeof x ==='number' || !!x

Elegant way of checking if a value is within a range and setting it's value if it falls outside of the range?

What I want to do is quite simple in itself, but I'm wondering is there is some really neat and compact way of accomplishing the same thing.
I have a float variable, and I want to check if it's value is between 0 and 1. If it's smaller than 0 I want to set it to zero, if it's larger than 1 I want to set it to 1.
Usually I do this:
// var myVar is set before by some calculation
if(myVar > 1){
myVar = 1;
}
if(myVar < 0){
myVar = 0;
}
Does anyone know of a more elegant/compact way of doing this?
One possible solution:
myVar = Math.min(1, Math.max(0, myVar));
Another:
myVar = myVar < 0 ? 0 : myVar > 1 ? 1 : myVar;
Use Math.min and Math.max, and avoid having a condition.
var MAX = 100;
var MIN = 50;
var val = 75;
console.log( Math.max(MIN, Math.min(MAX, val)) );
var val = 49;
console.log( Math.max(MIN, Math.min(MAX, val)) );
var val = 101;
console.log( Math.max(MIN, Math.min(MAX, val)) );
While the Min/Max solution is very succinct, it's far from obvious what is going on.
I would opt for a function that does just what you have:
myVar = constrainToRange(myVar, 0, 1);
function constrainToRange(x, min, max) {
if (x < min) {
x = min;
}
else if( x > max) {
x = max;
}
return x;
}
This is an option which can be expanded very easily to test more than simple min/max:
myVar = parseFloat( (myVar < 0 && '0') || (myVar > 1 && 1) || myVar );
The parseFloat and returning 0 as a string are important, otherwise it drops through that condition when it should stop there.
Maybe this:
myVal = myVal >= 1 ? 1 : Math.min(Math.abs(myVal), 0)

Categories

Resources