Chris
Chris

Reputation: 124

Is "if" or "switch" preferable Javascript

I am building a function which verifies a user's input makes sense in context of the application before it runs a block of code. I'm wondering whether an "if...else" statement like this or a switch statement is going to work more reliably/otherwise be a better solution? I lean toward if...else because I only have two outcomes--the user's input is either valid or tell the user what the program will accept, but I would like advice from somebody more experienced before I get too involved.

edit: For clarity, I only want my code to execute when i and o are both either "a" or "b", or both either "c" or "d", or both either "e" or "f".

    console.log("i="+i+" o="+o);
    if      
    (((i == ("a" || "b")) && (o == ("a" || "b")))
    ||  ((i == ("c" || "d")) && (o == ("c" || "d")))
    ||  ((i == ("e" || "f")) && (o == ("e" || "f"))))
    {
        //my block here
    }       
    else
    {
        //tell the user their input doesn't make sense
    }

Also, am I handling my Boolean operators correctly in this case?

Upvotes: 3

Views: 112

Answers (4)

Abhitalks
Abhitalks

Reputation: 28417

You could also do this:

var i='a', o='b', 
    allowed = [['a','b'], ['c', 'd'], ['e', 'f']];
function test(one, two) { 
    return allowed.some(function(elem) {
        return (elem.indexOf(one)>=0 && elem.indexOf(two)>=0);
    });
}
console.log(test(i, o));

Have an array of all of your allowed value pairs, and then use Array.prototype.some() to test if your i and o are within the allowed values. .some() will execute the callback function once for each element present in the array until it finds one where callback returns a true value. If such an element is found, it immediately returns true.

Here is a snippet:

// Only for this snippet
console.log = function(txt) {
    var result = document.getElementById("result");
    result.innerText += txt  + ", ";
}

// allowed values
var	i, o, allowed = [['a','b'], ['c', 'd'], ['e', 'f']];

// function to test
function test(one, two) { 
    return allowed.some(function(elem) {
   		return (elem.indexOf(one)>=0 && elem.indexOf(two)>=0);
	});
}

// all tests
i = 'a'; o = 'b';
console.log(test(i, o));
i = 'c'; o = 'd';
console.log(test(i, o));
i = 'e'; o = 'f';
console.log(test(i, o));
i = 'a'; o = 'c';
console.log(test(i, o));
i = 'd'; o = 'e';
console.log(test(i, o));
i = 'x'; o = 'y';
console.log(test(i, o));
<p id="result"></p>

And a fiddle to play with: http://jsfiddle.net/abhitalks/sfuxv4ov/

Upvotes: 1

Arun P Johny
Arun P Johny

Reputation: 388406

Instead of using so many or...and block which could make it unreadable, you can try a simple solution like below.

In this solution we first create a map of allowed values, and for each values what are the allowed combination for the second variable, then we check whether the value of a exists in the map, if so then we check whether the value of i is a permitted value in the allowed combination

function test(a, i) {
  var map = {
    a: ['a', 'b'],
    b: ['a', 'b'],
    c: ['c', 'd'],
    d: ['c', 'd'],
    e: ['e', 'f'],
    f: ['e', 'f']
  };

  if (map[a] && map[a].indexOf(i) > -1) {
    console.log('found', a, i, result === true)
  } else {
    console.log('not found', a, i, result === false)
  }
}

Upvotes: 4

Purag
Purag

Reputation: 17071

First, your Javascript doesn't work because non-empty strings evaluate to true, so ("c" || "d") just evaluates to "c". Meaning all you're currently checking is that i and o are the same value.

Indeed, this actually covers half of the cases that you need (if i and o are equal, you definitely proceed, regardless of whether they are "a", "b", etc).

The logic you want is this:

if( ((i == "a" || i == "b") && (o == "a" || o == "b")) ||
    ((i == "c" || i == "d") && (o == "c" || o == "d")) ||
    ((i == "e" || i == "f") && (o == "e" || o == "f"))
){
    // valid
} else {
    // invalid
}

I prefer that kind of if statement to the convoluted switch that you might end up with.

You could also approach it this way. You realize that i and o can be no more than one letter off from one another, so you can write this kind of logic:

if( Math.abs(i.charCodeAt(0) - o.charCodeAt(0)) <= 1 ){
    // valid
} else {
    // invalid
}

This is saying that as long as i and o are either the same letter or no more than one apart (using their ASCII values to compare), it's valid. Here's a demo.

check("a", "a")
// true
check("a", "b")
// true
check("a", "c")
// false
check("e", "f")
// true
check("a", "a")
// true
check("b", "a")
// true

Upvotes: 3

nem035
nem035

Reputation: 35491

Firstly, your if statement is wrong because JavaScript boolean expressions get coerced to boolean values.

Meaning:

'a'  ||  'b'

Will always return 'a' because 'a' evaluates to true and the JS engine has no need to check the second operand of the || statement.

So your if statement should look like:

if(((i == "a" || i == "b") && (o == "a" || o == "b")) ||
   ((i == "c" || i == "d") && (o == "c" || o == "d")) ||
   ((i == "e" || i == "f") && (o == "e" || o == "f"))

Upvotes: 4

Related Questions