javascript, combining AND, OR in an if starement - javascript

I would like my code to be able to do the following:
IF (value1 is less than -1 AND variable2 does not equal either 6 or 5) then...
So far I could get a single if and to work as follows;
if ( (value < -1 && (day !== 6)) ) sendEmail(value)
but as soon as I add in the second or it falls over. What am I doing wrong? I have tried it in a few different ways but below are a couple of examples that did not work.
if ( (value < -1 && (day !== 6 || 5)) ) sendEmail(value)
if ( (value < -1 && (day !== 6 || day !== 5)) ) sendEmail(value)

Think about your logic. Basically what you want is:
IF (value1 is less than -1 AND variable2 is not equal to 6 AND variable2 is not equal to 5)
Therefore your if statement can be written as:
if (value < -1 && day != 6 && day != 5) sendEmail(value);

if(value < -1 && day !== 6 && day !== 5) sendEmail(value)
should do the trick.

Related

Equality operator with multiple values in JavaScript

Is there a simple way to compare multiple values to a single value in Javascript ?
Like, instead of writing :
if (k != 2 && k != 3 && k!= 7 && k!12)
Writing something like :
if (k != {2,3,7,12})
You can use includes instead of multiple equality comparisons.
if (![2,3,7,12].includes(k))
That's boolean algebra:
if (k != 2 && k != 3 && k!= 7 && k != 12)
is equivalent to
if (!(k == 2 || k == 3 || k == 7 || k == 12))
and that's equivalent to
if (![2,3,7,12].includes(k))

Fundamental exercise to check divisibility of a number

I got stuck on this exercise. I don't understand why they need to have the first condition. Can I ignore that part?
The exercise is from https://www.w3resource.com/javascript-exercises/javascript-basic-exercise-46.php:
Write a JavaScript program to check two given non-negative integers that whether one of the number (not both) is multiple of 7 or 11.
function valCheck(a, b) {
if (!((a % 7 == 0 || a % 11 == 0) && (b % 7 == 0 || b % 11 == 0))) {
return ((a % 7 == 0 || a % 11 == 0) || (b % 7 == 0 || b % 11 == 0));
} else
return false;
}
console.log(valCheck(14, 21));
console.log(valCheck(14, 20));
console.log(valCheck(16, 20));
TL;DR – No, it's not redundant!
Write a JavaScript program to check whether exactly one of the two given non-negative integer numbers is a multiple of 7 or 11.
To explain why it's not redundant, let's break this solution function down.
function valCheck(a, b) {
if (!((a % 7 == 0 || a % 11 == 0) && (b % 7 == 0 || b % 11 == 0))) {
return ((a % 7 == 0 || a % 11 == 0) || (b % 7 == 0 || b % 11 == 0));
} else
return false;
}
First Conditional
The first condition is !((a % 7 == 0 || a % 11 == 0) && (b % 7 == 0 || b % 11 == 0)). The x % n == 0 expressions are checking whether the given x is divisible by (a multiple of) either 7 or 11, but the expression is written in an overly verbose way that makes it a little difficult to understand.
Using De Morgan's law, we can rewrite it:
!((a % 7 == 0 || a % 11 == 0) && (b % 7 == 0 || b % 11 == 0))
⇔
!(a % 7 == 0 || a % 11 == 0) || !(b % 7 == 0 || b % 11 == 0)
⇔
(a % 7 != 0 && a % 11 != 0) || (b % 7 != 0 && b % 11 != 0)
Now, we can tell that this condition is checking for the case where either a or b isn't divisible by 7 nor 11.
When this condition is true, we return the result of a second condition. If it is false, then we know neither input is a multiple of 7 or 11, so we return false outright.
Second Conditional
The second condition is:
(a % 7 == 0 || a % 11 == 0) || (b % 7 == 0 || b % 11 == 0)
This one is much less opaque than the first, and checks whether any of the 4 sub-conditions are true (the parenthesis are irrelevant here, since they're all "or" || operators).
Since we already know from the first condition that at least one of the inputs isn't a multiple of 7 or 11, we can now simply return whether at least of the inputs is. Put another way, if we know that this second condition is true, then we can be certain that exactly one of the numbers is a multiple of 7 or 11.
Are the Conditions Redundant?
So to answer your question, no, the first conditional isn't redundant, since it checks for whether at least one of the inputs isn't a multiple or 7 or 11. We need both of the conditional expressions to properly check that exactly one of the inputs is a proper multiple or 7 or 11.
If the "but not both" clause wasn't there, then we could use just the second conditional expression, but since it is, we need both pieces of information.
Wanted to note, I lied a little in saying we need both expressions, since it is indeed possible to solve this exercise with a single expression!
function valCheck(a, b) {
return (a % 7 == 0 || a % 11 == 0) != (b % 7 == 0 || b % 11 == 0);
}
console.log(valCheck(14, 21)); // false
console.log(valCheck(14, 20)); // true
console.log(valCheck(16, 20)); // false
I'll leave it to the reader to figure out why this works!
There are many repeating functions, let's refactor for clarity:
function isMultipleOf7Or11(num) {
return num % 7 == 0 || num % 11 == 0;
}
function valCheck(a, b) {
var isAVarMultiple = isMultipleOf7Or11(a);
var isBVarMultiple = isMultipleOf7Or11(b);
if(!(isAVarMultiple && isBVarMultiple) {
return isAVarMultiple || isBVarMultiple;
else
return false;
}
}
Now to simplify the condition:
!(isAVarMultiple && isBVarMultiple) is also equal to !isAVarMultiple || !isBVarMultiple according to De Morgan's negation of a conjuction, which returns true if at least one of them is not a multiple of 7 or 11
and in the return value the condition isAVarMultiple || isBVarMultiple returns true if at least one of them is a multiple of 7 or 11
We can conclude that it is a XOR operation on two values, which would return true only if one and only one of the variables is a multiple of 7 or 11
Outputs:
console.log(valCheck(14, 21));
returns false
console.log(valCheck(14, 20));
returns true
console.log(valCheck(16, 20));
returns false
I recommend you look at the code by the debugger, not for this example only, but when you will be stuck in difficult situations, you can split your code in a small and readable pieces and see what is happening in there.
For example this can be transformed to this
Not Sure If I can make this more readable :)
function valCheck (a, b) {
debugger;
const canADividedTo7 = a % 7 == 0;
const canADividedTo11 = a % 11 == 0;
const canADividedTo7Or11 = canADividedTo7 || canADividedTo11;
const canBDividedTo7 = b % 7 == 0;
const canBDividedTo11 = b % 11 == 0;
const canBDividedTo7Or11 = canBDividedTo7 || canBDividedTo11;
// true when both both side of expression are true
const canAAndBDividedTo7Or11 = canADividedTo7Or11 && canBDividedTo7Or11;
// true when at least one of the expression is true
const canAOrBDividedTo7Or11 = canADividedTo7Or11 || canBDividedTo7Or11;
//
if (!canAAndBDividedTo7Or11) {
return canAOrBDividedTo7Or11;
} else {
return false;
}
}
console.log(valCheck(14, 21));
console.log(valCheck(14, 20));
console.log(valCheck(16, 20));
Who would write anything that inane and complicated?
Let's take this mess:
function valCheck(a, b) {
if (!((a % 7 == 0 || a % 11 == 0) && (b % 7 == 0 || b % 11 == 0))) {
return ((a % 7 == 0 || a % 11 == 0) || (b % 7 == 0 || b % 11 == 0));
} else
return false;
}
and refactor it into something readable:
function valChec( a, b ) {
const aIsDivisible = a % 7 === 0 || a % 11 === 0 ;
const bIsDivisible = b % 7 === 0 || b % 11 === 0 ;
return aIsDivisible ? !bIsDivisible : bIsDivisible;
}
You could even make it a one-liner with a ternary expression (at the expense of a few more division ops... but given the original code, that's not an issue):
const isMagic = x => x % 7 === 0 || x % 11 === 0;
const valCheck = (a,b) => isMagic(a) ? !isMagic(b) : isMagic(b);
Yes, you're right in finding the answer to that question redundant; also, I believe the ! is incorrect and makes the code always return false.
A more reasonable solution to the problem would be to just return the boolean expression:
function valCheck(a, b) {
return ((a % 7 == 0 || a % 11 == 0) || (b % 7 == 0 || b % 11 == 0));
}
Alternatively, if you really wanted to use an if/else construct, it would be better to just return true in the first case:
function valCheck(a, b) {
if ((a % 7 == 0 || a % 11 == 0) && (b % 7 == 0 || b % 11 == 0))
return true;
else
return false;
}
Hope this helps with your understanding of JavaScript! But as suggested in the comments, you might want to learn JavaScript from other sources.

2D Array in While loop bounds

I'm having some issues with figuring out how to work with a 2D array and a while loop.
Here's the relevant code snippet:
while (
table[i - count][j] === 0 ||
table[i + count][j] === 0 ||
table[i][j - count] === 0 ||
table[i][j + count] === 0
) { ... count++; }
I get the following error when running my snippet:
TypeError: Cannot read property '0' of undefined
Now I understand that this is happening because if I have i = 0 then table[i - count][j] would been it is checking table[-1][j]. Obviously this shouldn't work but that is the purpose of the while loop that I've implemented.
I want the code to stop running when either the edge of this 2D array is out of bounds (like explained above) or if the element's value is 0.
Currently it gives me the error when I just need it to stop and carry on with the code after the while loop. How do I solve this?
EDIT:
Yeah I'm sure I want these conditions to be &&. The main issue is that i -count could result in a negative number. Or i + count could result in a number out of bounds for the array.
How do I deal with those out of bounds occasions in this while loop?
You need to make shure the array exists before accessing its keys, and checking for 0 or undefined is irrelevant as both are falsy :
while(
(table[i - count] || [])[j] &&
(table[i + count] || [])[j] &&
(table[i] || [])[j + count] &&
(table[i] || [])[j - count]
) count++;
Right I've found a solution. It's probably not optimal in general but for what I'm doing it's perfect:
while (
i - count >= 0 &&
j - count >= 0 &&
i + count < table.length &&
j + count < table[i].length
) {
if (
table[i - count][j] === 0 ||
table[i + count][j] === 0 ||
table[i][j - count] === 0 ||
table[i][j + count] === 0
) return prod;
prod *= (
table[i - count][j] *
table[i + count][j] *
table[i][j - count] *
table[i][j + count]
);
count++;
}
As commented before, using I would suggest using a function that returns a boolean value. This will keep your loop clean and you can choose to have a more descriptive code for conditions.
function validate(array, i, j, count){
// To cover case when either variable is 0
if(i && j){
let prev = array[i - count];
let next = array[i + count];
let curr = array[i];
return (
(j < prev.length && prev[j] === 0) ||
(j < next.length && next[j] === 0) ||
// Since we have already added a check for value !== 0,
// we just have to check for out of bound here.
(j < curr.length -1) && (
curr[j - count] === 0 ||
curr[j + count] === 0
)
)
}
return false;
}
while (validate(table, i, j, count)) { ... count++; }
Assuming your conditions are connected by "and"
Just add extra conditions to check for valid values/bounds for your array index
while (
table[i - count][j] !== 0 && table[i - count][j] !== undefined &&
table[i + count][j] !== 0 && table[i + count][j] !== undefined &&
table[i][j - count] !== 0 && table[i][j - count] !== undefined &&
table[i][j + count] !== 0 && table[i][j + count] !== undefined &&
i - count > 0 &&
j - count > 0
) { ... count++; }

Why does javascript accept a decimal as an integer

I have this html:
<input type='number' id='length' step='0.1' min='0'; max='5'>Length
and this Javascript
num=document.getElementById('length').value;
if(num==1 || 2 || 3 || 4|| 5){
num='0'+num;
}
My problem is this: while I only want the code inside the brackets to execute if the number from the input is an integer, it also activates if it detects 0.8 or some other decimal. Any Idea why? How do I fix it? Thanks.
To make sure num is a whole number, without having to define all possibilities, use:
if (num % 1 == 0)
Why:
num==1 || 2 || 3 || 4|| 5
equals to:
(num==1) || 2 || 3 || 4|| 5
so if num is "1" (always a string type), the expression returns true, otherwise 2 (also a truthy value), eventually your if statement always succeeds.
How to fix:
// implicitly converts the string type into number type before comparison
// returns true if it is an integer-like string
num == Math.floor(num)
So you could do it like this:
if (num == Math.floor(num) && num > 0 && num < 6) {
// an integer-like string that meets the requirement [1, 5]
}
But remember, the num is still string type now. If you want a number, do:
num = +num
You should do
if (num == 1 || num == 2 || num == 3 || num == 4 || num == 5)
WRONG - otherwise it will compare 2 with 2 and says it's true for the 4 last 'if' parameters.
CORRECTO - any number in JS is considered as true.
You have to edit the "If" loop:
if (num == 1 || num == 2 || num == 3 || num == 4 || num == 5)

Location.pathname.indexOf not working with 'Or' ( || )

I'm trying to use location.pathname.indexOf to make conditional jQuery work on some pages on my site.
This works:
if (location.pathname.indexOf("/example/5820.htm") != 0){}
This works:
if (location.pathname.indexOf("/example-1/3569.htm") != 0) {}
This doesn't work:
if (location.pathname.indexOf("/example/5820.htm") != 0 || location.pathname.indexOf("/example-1/3569.htm") != 0) {}
I've done this a ton of times and for some reason this code is not working. I'm wondering if I'm missing something little in the code or if it's something else?
Tim already answered this question, but don't forget:
.indexOf() will return -1 when the string isn't found, not 0.
if (location.pathname.indexOf("/example/5820.htm") != 0){}
Should be:
if (location.pathname.indexOf("/example/5820.htm") != -1){}
Or:
if (location.pathname.indexOf("/example/5820.htm") >= 0){}
http://www.w3schools.com/jsref/jsref_indexof.asp
basically you're saying this:
var a = 0;
var b = 1;
if (a != 0 || b != 0) {};
Which is equal to
if (!(a == 0 && b == 0)) {};
However, you actually want this:
if (!(a == 0 || b == 0)) {};
Which is equal to:
if (a != 0 && b != 0) {};

Categories