Switch statement in if else conditional, else not being reached - javascript

This is a shortened version of a conditional I've written to parse information from a vehicle VIN number. If I pass in a VIN such as JA3XXXXXXXXXXXXXX it returns and object with properties of region:'Asia';, country:'Japan'; and make:'Isuzu'; but if I pass it 2A5XXXXXXXXXXXXXX I would expect an object with properties set to region:'North America'; , country:'Canada'; and make:'Chrysler'; instead I get an object with the region property set to 'Asia' and that is it. Here is a jsFiddle with the code shown below.
var vehicle = {},
nthDigit = function (stringifiedVin, i) {
var nthChar = stringifiedVin.charAt(i);
return nthChar;
},
parseVin = function () {
var i = 0;
for (i = 0; i < 16; i += 1) {
if (i === 0) {
if (nthDigit(stringifiedVin, 0) === 'J' || 'K' || 'L' || 'M' || 'N' || 'P' || 'R') {
vehicle.region = 'Asia';
switch (nthDigit(stringifiedVin, i)) {
case 'J':
vehicle.country = 'Japan';
switch (nthDigit(stringifiedVin, 1)) {
case 'A':
if (nthDigit(stringifiedVin, 2) === 'A' || 'B' || 'C' || 'D' || 'E' || 'F' || 'G' || 'H' || 'J' || 'K' || 'L' || 'M' || 'N' || 'P' || 'R' || 'S' || 'T' || 'U' || 'V' || 'W' || 'X' || 'Y' || 'Z') {
vehicle.make = 'Isuzu';
} else if (nthDigit(stringifiedVin, 2) === '3' || '4' || '5' || '6' || '7') {
vehicle.make = 'Mitsubishi';
} else {
vehicle.make = 'Not Read';
}
break;
}
break;
}
} else if (nthDigit(stringifiedVin, 0) === '1' || '2' || '3' || '4' || '5') {
vehicle.region = 'North America';
if (nthDigit(stringifiedVin, 0) === '2') {
vehicle.country = "Canada";
switch (nthDigit(stringifiedVin, 1)) {
case 'A':
if (nthDigit(stringifiedVin, 2) === '2' || '3' || '4' || '5' || '6' || '7' || '8') {
vehicle.make = 'Chrysler';
} else {
vehicle.make = 'Not Read';
}
break;
}
break;
}
}
return vehicle;
}
}
}

I don't thing the || parts work the way you think they do. This will run the Alert() since '2' is not false:
if ('A' === '1' || '2')
alert('match')
I would use a switch or you will have to spell it out like:
var nd = nthDigit(stringifiedVin, 0);
if (nd === 'J' || nd === 'K' || nd === 'L' || ...

A shorter one:
if("JKLMNP".indexOf(nthDigit(stringifiedVin, 0)) > -1){
//....
}

#JBrooks I think you are right about how the double pipe or operator was causing trouble in the conditional statement. I think it is due to the way the operator handles falsy values as shown in this SO post. I ended up getting rid of the if statements entirely when I realized the JA3XXXXXXXXXXXXXX should have been returning Mitsubishi and not Isuzu. I found the solution here using #KennyTM answer on setting up multiple cases.

Related

Javascript filtering with multiple parameters

I need to filter my content with multiple parameters that I am taking from fields. The fields could also be empty, so I need to get all the values that are not empty. And filter by those.
What is the best way to achieve this without making a lot of if and else if conditions like this:
if (a !== '' && b !== '' && c !== '' && d !== '' && e !== ''){
// none is empty, filter by a & b & c & d & e
}
else if ( b !== '' && c !== '' && d !== '' && e !== ''){
// a is empty, filter by b & c & d & e
}
else if ( a !== '' && c !== '' && d !== '' && e !== ''){
// b is empty, filter by a & c & d & e
}
else if ( b !== '' && a !== '' && d !== '' && e !== ''){
}
else if ( b !== '' && c !== '' && a !== '' && e !== ''){
}
else if ( b !== '' && c !== '' && d !== '' && a !== ''){
}
else if ( c !== '' && d !== '' && e !== ''){
}
else if ( b !== '' && d !== '' && e !== ''){
}
else if ( b !== '' && c !== '' && e !== ''){
}
else if ( b !== '' && c !== '' && d !== ''){
}
else if ( a !== '' && d !== '' && e !== ''){
}
and so on...
Alternatively, how can I get all the unique possible combination of these 5 letters?
Edit ::
The actual code would look something like this
//a/b/c take value of dropdown items, that match with data on an object
if (a != '' && b != '' && c != '') {
for (const i in ParticipationList.TaskMetadata) {
if (ParticipationList.TaskMetadata[i].attendance == a && ParticipationList.TaskMetadata[i].monitoring_status == b && ParticipationList.TaskMetadata[i].monitoring_status == c) {
filteredaudience[i] = { ['id']: i }
}
console.log(filteredaudience)
// get all the items that match with the object properties
}
}
So if a or b or c is empty, I can't still make the same call, as it would not match anything on the object.
The logic:
Since javascript has short-circuit evaluation, we'll just use a bunch of conditions in the format:
field === "" || (condition to filter using field)
Because of said "short-circuiting", the right side part will only be reached if the field is not empty (i.e. if the left side is false because field !== ""). However, if the field is empty then field === "" will be true and the right side part won't be reached and the whole condition will yield true resulting in the filtering for this field to be skipped.
Multiple conditions should be joined together by the logical && operator and each one of those conditions should be wrapped in parenthesis () because the operator && is higher in precedence than the || operator.
If the data to filter is an array:
For arrays, just use the conditions as the value returned from the callback of filter like so:
let filteredData = data.filter(item =>
(a === "" || (condition for field 'a' against 'item'))
&&
(b === "" || (condition for field 'b' against 'item'))
&&
(c === "" || (condition for field 'c' against 'item'))
&&
(d === "" || (condition for field 'd' against 'item'))
&&
(e === "" || (condition for field 'e' against 'item'))
);
If the data to filter is an object:
In case the data is an object and you can't use filter like above, you can still use the same logic, you just have to use the conditions inside if like so:
let filteredaudience = {};
for (const i in ParticipationList.TaskMetadata) {
if ((a === "" || ParticipationList.TaskMetadata[i].attendance === a)
&& (b === "" || ParticipationList.TaskMetadata[i].monitoring_status === b)
&& (c === "" || ParticipationList.TaskMetadata[i].monitoring_status === c)
&& (d === "" || ParticipationList.TaskMetadata[i].?????????? === d)
&& (e === "" || ParticipationList.TaskMetadata[i].?????????? === e)) {
filteredaudience[i] = { id: i };
}
}
Depending on how the actual filtering process works, it might be possible to incrementally filter your result instead of doing it simultaneously.
For example, if your data is an array, you might write:
let data = ...;
if (a != '') {
data = data.filter(elem => checkForA(a, elem));
}
if (b != '') {
data = data.filter(elem => checkForB(b, elem));
}
...
Maybe you can also incrementally augment the filter object itself and THEN apply the built filter.
Please enter more details ...
For now, what I understood was that you want to get all the
values that are not empty.
for this:
let allElements = [a, b, c, d, e]
let notEmpty = []
allElements.forEach(element => {
if (element !== '')
notEmpty.push(element)
});
console.log(notEmpty)
A common mistake for new developers is to create long, complicated and repetative if statements with tons of && and || symbols or long strings of if/else if
Instead of this, write a simple search predicate. This is a function which takes some parameters, and reduces them to either true or false.
Within said function, run each filter one at a time. As soon as one fails, return false.
var data = [
{ colour : "red", weight : 2, name : "Example 1"},
{ colour : "orange", weight : 15, name : "Example 2"},
{ colour : "yellow", weight : 10, name : "Test 1"},
{ colour : "green", weight : 24, name : "Test 2"}
];
console.log(search(data, "red", [], ""));
console.log(search(data, "", [5,20], ""));
console.log(search(data, "", [], "Test"));
function search(data, colour, weights, name) {
return data.filter(row=>testRow(colour, weights, name, row));
}
// much easier to read.
function testRow(colourFilter, weightFilter, nameSearchFilter, row) {
// run each filter one at a time. If any fail, "short circuit" out.
if (colourFilter != "" && row.colour == colourFilter) {
return false;
}
// sometimes, a double if statemnt is easier to read.
if (weightFilter.length > 0) {
if (row.weight < weightFilter[0] || row.weight > weightFilter[1]) {
return false;
}
}
// sometimes, the actual rule is a bit complex.
if (nameSearchFilter != "") {
if (row.name.indexOf(nameSearchFilter) < 0) {
return false;
}
}
// we survived all filters.
return true;
}

Make an vertical array horizontal in js (discord.js)

I want to make a vertical array to be a vertical array in discord.js
This is supposed to send the text in regional letters horizontally, but it send vertically. I checked on stackoverflow, but i found nothing about what i wanted to do , so if you could help me out, this should be nice.
Here is my code:
var Letters = {
a:":regional_indicator_a:",
b:":regional_indicator_b:",
c:":regional_indicator_c:",
d:":regional_indicator_d:",
e:":regional_indicator_e:",
f:":regional_indicator_f:",
g:":regional_indicator_g:",
h:":regional_indicator_h:",
i:":regional_indicator_i:",
j:":regional_indicator_j:",
k:":regional_indicator_k:",
l:":regional_indicator_l:",
m:":regional_indicator_m:",
n:":regional_indicator_n:",
o:":regional_indicator_o:",
p:":regional_indicator_p:",
q:":regional_indicator_q:",
r:":regional_indicator_r:",
s:":regional_indicator_s:",
t:":regional_indicator_t:",
u:":regional_indicator_u:",
v:":regional_indicator_v:",
w:":regional_indicator_w:",
x:":regional_indicator_x:",
y:":regional_indicator_y:",
z:":regional_indicator_z:"
};
let args = message.content.split(" ").slice(1);
let data = args.slice(0).join(" ");
var chars = data.split('');
function getRegional(letter){
if(letter === "a" || letter === "A"){ return Letters.a; }
if(letter === "b" || letter === "B"){ return Letters.b; }
if(letter === "c" || letter === "C"){ return Letters.c; }
if(letter === "d" || letter === "D"){ return Letters.d; }
if(letter === "e" || letter === "E"){ return Letters.e; }
if(letter === "f" || letter === "F"){ return Letters.f; }
if(letter === "g" || letter === "G"){ return Letters.g; }
if(letter === "h" || letter === "H"){ return Letters.h; }
if(letter === "i" || letter === "I"){ return Letters.i; }
if(letter === "j" || letter === "J"){ return Letters.j; }
if(letter === "k" || letter === "K"){ return Letters.k; }
if(letter === "l" || letter === "L"){ return Letters.l; }
if(letter === "m" || letter === "M"){ return Letters.m; }
if(letter === "n" || letter === "N"){ return Letters.n; }
if(letter === "o" || letter === "O"){ return Letters.o; }
if(letter === "p" || letter === "P"){ return Letters.p; }
if(letter === "q" || letter === "Q"){ return Letters.q; }
if(letter === "r" || letter === "R"){ return Letters.r; }
if(letter === "s" || letter === "S"){ return Letters.s; }
if(letter === "t" || letter === "T"){ return Letters.t; }
if(letter === "u" || letter === "U"){ return Letters.u; }
if(letter === "v" || letter === "V"){ return Letters.v; }
if(letter === "w" || letter === "W"){ return Letters.w; }
if(letter === "x" || letter === "X"){ return Letters.x; }
if(letter === "y" || letter === "Y"){ return Letters.y; }
if(letter === "z" || letter === "Z"){ return Letters.z; }
if(letter === " "){ return ' '; }
}
var LettersToSend = [];
chars.forEach(element => {
console.log('Lettre: ' + element)
console.log('Regional letter: ' + getRegional(element))
LettersToSend.push(getRegional(element));
});
Here is the output:
I hope that you can help me.
Thanks.
Here is an optimised version of your code that should give you the correct results.
Any characters that aren't letters are replaced with a space.
let args = message.content.split(' ').slice(1);
let data = args.slice(0).join(' ');
let chars = data.split('');
function getRegional(letter) {
return (!/^[a-zA-Z]$/g.test(letter))? ' ' :
`:regional_indicator_${ letter.toLowerCase() }:`;
}
let lettersToSend = [];
lettersToSend = chars.map(element => {
console.log('Letter: ' + element);
console.log('Regional letter: ' + getRegional(element));
return getRegional(element);
});
message.channel.send(lettersToSend.join(' '));
this code should work for you.
function exec(message) {
var hash = {
a: ":regional_indicator_a:",
b: ":regional_indicator_b:",
c: ":regional_indicator_c:",
d: ":regional_indicator_d:",
e: ":regional_indicator_e:",
f: ":regional_indicator_f:",
g: ":regional_indicator_g:",
h: ":regional_indicator_h:",
i: ":regional_indicator_i:",
j: ":regional_indicator_j:",
k: ":regional_indicator_k:",
l: ":regional_indicator_l:",
m: ":regional_indicator_m:",
n: ":regional_indicator_n:",
o: ":regional_indicator_o:",
p: ":regional_indicator_p:",
q: ":regional_indicator_q:",
r: ":regional_indicator_r:",
s: ":regional_indicator_s:",
t: ":regional_indicator_t:",
u: ":regional_indicator_u:",
v: ":regional_indicator_v:",
w: ":regional_indicator_w:",
x: ":regional_indicator_x:",
y: ":regional_indicator_y:",
z: ":regional_indicator_z:"
};
var msg = "";
var letters = args.join(" ");
function getRegional(letter) {
return (letter === " " ? " " : hash[letter])
}
for (i = 0; i < letters.length; i++) {
msg += getRegional(letters[i])
}
console.log(msg)
}
let msg = {
content: '!regional two three'
}
let [command, ...args] = msg.content.slice(1).split(/\s+/g)
exec(args)
running this code returned this for me (im assuming this is what you want)
:regional_indicator_t::regional_indicator_w::regional_indicator_o: :regional_indicator_t::regional_indicator_h::regional_indicator_r::regional_indicator_e::regional_indicator_e:
Well, instead of doing that many if you can just check for the property.
variable.property could also be written as variable['propery'] with the difference you can add variables. so in the getRegional(letter) you can check for a property you passed down. if(!Letters[letter]) return ' ';. Then return the property.
var Letters = {
a: ":regional_indicator_a:",
b: ":regional_indicator_b:",
c: ":regional_indicator_c:",
d: ":regional_indicator_d:",
e: ":regional_indicator_e:",
f: ":regional_indicator_f:",
g: ":regional_indicator_g:",
h: ":regional_indicator_h:",
i: ":regional_indicator_i:",
j: ":regional_indicator_j:",
k: ":regional_indicator_k:",
l: ":regional_indicator_l:",
m: ":regional_indicator_m:",
n: ":regional_indicator_n:",
o: ":regional_indicator_o:",
p: ":regional_indicator_p:",
q: ":regional_indicator_q:",
r: ":regional_indicator_r:",
s: ":regional_indicator_s:",
t: ":regional_indicator_t:",
u: ":regional_indicator_u:",
v: ":regional_indicator_v:",
w: ":regional_indicator_w:",
x: ":regional_indicator_x:",
y: ":regional_indicator_y:",
z: ":regional_indicator_z:"
};
let args = message.content.split(" ").slice(1);
let data = args.slice(0).join(" ");
var chars = data.split('');
function getRegional(letter) {
if(!Letters[letter.toLowerCase()]) return ' '; // If property doesn't exist return ''
return Letters[letter.toLowerCase()]; // If it does, return it.
}
var LettersToSend = [];
chars.forEach(element => {
console.log('Lettre: ' + element)
console.log('Regional letter: ' + getRegional(element))
LettersToSend.push(getRegional(element));
});
message.channel.send(LettersToSend.join('')); // Send it in a single String.
Hope this code helps and makes it Easier.

I am not getting any output for this js code

This is the code -
<input type="text" id="field">
<input type="button" onclick="test()">
<p id="demo"></p>
<script type="text/javascript">
function test(){
var a = document.getElementById("field").value;
var b = a.split(" ");
for(var i=0; i<b.length; i++){
var x[i] = 0;
for(var j=0; j<b[i].length; j++){
if(b[i][j] == 'e' || b[i][j] == 'a' || b[i][j] == 'i' || b[i][j] == 'o' || b[i][j] == 'n' || b[i][j] == 'r' || b[i][j] == 't' || b[i][j] == 'l' || b[i][j] == 's' || b[i][j] == 'u'){
x[i]++;
}
else if(b[i][j] == 'd' || b[i][j] == 'g'){
x[i]+=2;
}
else if(b[i][j] == 'b' || b[i][j] == 'c' || b[i][j] == 'm' || b[i][j] == 'p'){
x[i]+=3;
}
else if(b[i][j] == 'f' || b[i][j] == 'h' || b[i][j] == 'w' || b[i][j] == 'y'){
x[i]+=4;
}
else if(b[i][j] == 'k'){
x[i]+=5;
}
else if(b[i][j] == 'j' || b[i][j] == 'x'){
x[i]+=8;
}
else{
x[i]+=10;
}
}
}
document.getElementById("demo").innerHTML = x[0];
/*if(x[0] > x[1]){
document.getElementById("demo").innerHTML = b[0];
}
else{
document.getElementById("demo").innerHTML = b[1];
}*/
}
</script>
</body>
I am not getting any output for this code. I am printing here x[0] but not getting anything. Please help me with this code. What's wrong in this code. I tried everything.
Please Try This
function test(){
var a = document.getElementById("field").value;
var b = a.split(" "),x;
var x =[];
for(var i=0; i<b.length; i++){
x[i] = 0;
for(var j=0; j<b[i].length; j++){
if(b[i][j] == 'e' || b[i][j] == 'a' || b[i][j] == 'i' || b[i][j] == 'o' || b[i][j] == 'n' || b[i][j] == 'r' || b[i][j] == 't' || b[i][j] == 'l' || b[i][j] == 's' || b[i][j] == 'u'){
x[i]++;
}
else if(b[i][j] == 'd' || b[i][j] == 'g'){
x[i]+=2;
}
else if(b[i][j] == 'b' || b[i][j] == 'c' || b[i][j] == 'm' || b[i][j] == 'p'){
x[i]+=3;
}
else if(b[i][j] == 'f' || b[i][j] == 'h' || b[i][j] == 'w' || b[i][j] == 'y'){
x[i]+=4;
}
else if(b[i][j] == 'k'){
x[i]+=5;
}
else if(b[i][j] == 'j' || b[i][j] == 'x'){
x[i]+=8;
}
else{
x[i]+=10;
}
}
}
document.getElementById("demo").innerHTML = x[0];
/*if(x[0] > x[1]){
document.getElementById("demo").innerHTML = b[0];
}
else{
document.getElementById("demo").innerHTML = b[1];
}*/
}
You declared the x array inside a for loop therefore it's not available outside of it. Try moving the declaration outside of the loop.
This issue is caused by your wrong array declaration var x[i] = 0;
Change it to something like this: var x = new Array();
Then access each index via x[index]
See https://www.w3schools.com/js/js_arrays.asp
Try this:
function test(){
var a = document.getElementById("field").value;
console.log(a);
var b = a.split(" ");
console.log(b);
for(var i = 0; i < b.length; i++) {
var x = [];
x[i] = 0;
for(var j=0; j<b[i].length; j++){
if(b[i][j] == 'e' || b[i][j] == 'a' || b[i][j] == 'i' || b[i][j] == 'o' || b[i][j] == 'n' || b[i][j] == 'r' || b[i][j] == 't' || b[i][j] == 'l' || b[i][j] == 's' || b[i][j] == 'u'){
x[i]++;
}
else if(b[i][j] == 'd' || b[i][j] == 'g'){
x[i]+=2;
}
else if(b[i][j] == 'b' || b[i][j] == 'c' || b[i][j] == 'm' || b[i][j] == 'p'){
x[i]+=3;
}
else if(b[i][j] == 'f' || b[i][j] == 'h' || b[i][j] == 'w' || b[i][j] == 'y'){
x[i]+=4;
}
else if(b[i][j] == 'k'){
x[i]+=5;
}
else if(b[i][j] == 'j' || b[i][j] == 'x'){
x[i]+=8;
}
else{
x[i]+=10;
}
}
document.getElementById("demo").innerHTML = x[b.length -1];
}
}
<input type="text" id="field">
<input type="button" onclick="test()">
<p id="demo"></p>
This line itself is a problem var x[i] = 0; That's not how you declare an array. Here is how you do it var x = []; but since you want to set the first element to 0 then you can do this var x = [0]; just replace this line and your code should work.
Also to check the problem your code in the future when you encounter error, on browser press F12 key to open developer tools then see the console window/tab and it'll tell you exactly what the problem in your code.
EDIT
After reading your code again I saw that #Ankul Chaudhary 's answer is probably what you wanted to achieve since in the comment in your code you intent to compare items inside array x which in his solution he declared array x outside of the loop which it won't reset its values and keep all the calculated values inside the array which allow you to access later in the code

Validate CreditCard Number and checked radio button javascript

I have radio buttons radioVisa, and radioMaster. If either one is checked, I need to first check to see which one is selected and then validate that the card number entered is valid. I also need to make sure that only numbers are entered.... I am not allowed to use any regular expression techniques.... If the radioVisa is checked, it seems to work but when I added the code for the radioMaster, if it is checked it does't work.... Can someone tell me what I am doing wrong please....
function isValidCardNumber(num, isVisa, isMaster){
var card = new Array();
if (document.getElementById('radioVisa').checked){
card = isVisa;
}
if (num[0] != '4' || num.length != 16 ){
return false;
} else {
return true;
} else if (document.getElementById('radioMaster').checked){
card = isMaster;
}
if (num[0] != '51' || num[0] != '52' || num[0] != '53' ||
num[0] != '54' || num[0] != '55' || num.length != 16 ){
return false;
} else {
return true;
}
if (num[0] != '51' || num[0] != '52' || num[0] != '53' ||
num[0] != '54' || num[0] != '55' || num.length != 16 )
You can not combine all those numbers.You need to specify individually.
or
var numbers= ["51", "52", "53", "54",55];
var index = numbers.indexOf(num[0]);
It will return -1 if that is not exist otherwise return the index

Why is this function not working

I want to convert a string to integer. I know that there are built-in functions to do it, but still i want to know why is this function not working:
JS: - saved as js1.js
function atoi(str)
{
l = str.length;
s2 = "0"
for(i=0;i<l;i++)
{
if(str.charAt(i) != '1' || str.charAt(i) != '2' || str.charAt(i) != '3' || str.charAt(i) != '4' || str.charAt(i) != '5' || str.charAt(i) != '6' || str.charAt(i) != '7' || str.charAt(i) != '8' || str.charAt(i) != '9' || str.charAt(i) != '0')
{
break;
}
s2 = s2.concat(str.charAt(i));
}
return Number(s2);
}
HTML:
<html>
<head>
<script src="js1.js">
</script>
<Script>
function printnum()
{
n = atoi(document.getElementById('numtxt').value)
document.write(n);
}
</script>
<title>
Test JS1 functions
</title>
</head>
<body>
<input type="text" id="numtxt">
<input type="button" onclick="printnum()">
</body>
</html>
Thank You.
You give up and break if the first character is not a 1 or if it is not a 2, etc.
If it is 1 then it isn't 2 and you break.
You want to be using && not ||.
this or-thing you have there is always true, like:
If a!=3||a!=4
any value a can have, this is always true, so is with more terms
You shoud use && instead of ||
if(str.charAt(i) != '1' && str.charAt(i) != '2' &&
str.charAt(i) != '3' && str.charAt(i) != '4' &&
str.charAt(i) != '5' && str.charAt(i) != '6' &&
str.charAt(i) != '7' && str.charAt(i) != '8' &&
str.charAt(i) != '9' && str.charAt(i) != '0')

Categories

Resources