0

So while playing around with some js code, I came across something interesting. The problem statement goes like-
Given a string, use switch case to evaluate the following conditions:-
If the first character in string is in the set {a, e, i, o, u}, then return A.
If the first character in string is in the set {b, c, d, f, g}, then return B.
If the first character in string is in the set {h, j, k, l, m}, then return C.
If the first character in string is in the set {n, p, q, r, s, t, v, w, x, y, z}, then return D.
And I KNOW that this is not the best implementation, so don't @ me.

function getLetter(s) {
    let letter;
    switch(s[0]){
        case 'a'||'e'||'i'||'o'||'u':
            letter='A'
            break
        case 'b'||'c'||'d'||'f'||'g':
            letter='B'
            break
        case 'h'||'j'||'k'||'l'||'m':
            letter='C'
            break
        case 'n'||'p'||'q'||'r'||'s'||'t'||'v'||'w'||'x'||'y'||'z':
            letter='D'
            break
    }
    return letter;
    

All cases except the last one work fine. In the last case, the value of 'letter' is set to 'D' only if the string begins with 'n' & not for any other characters in the case label. Why is this happening? Genuinely Curious.

enCrypt
  • 21
  • 4
  • 1
    The cases are checking the first operand of the logical or expressions only. Using lookup tables instead of `switch` would resolve this problem. – Teemu Apr 10 '21 at 12:55
  • 1
    It's not about the _"best implementation"_ here. Your implementation is incorrect. `x || y` is an expression, it is evaluated the same way in any context, including when you use it as a `case` label in a switch. Its value is the value of `x` if the value of `x` is true when it is evaluated as boolean or the value of `y` otherwise (no matter the value of `y`). This means the value of `'a'||...` is always `'a'`, no matter what other values you put after the [logical OR operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_OR). – axiac Apr 10 '21 at 13:00

3 Answers3

1

In JavaScript, a || b returns the value of a if it is truthy (this is commonly answered elsewhere on Stack Overflow). Since non-empty strings are truthy, this is what your switch statement effectively looks like:

    switch(s[0]){
        case 'a':
            letter='A'
            break
        case 'b':
            letter='B'
            break
        case 'h':
            letter='C'
            break
        case 'n':
            letter='D'
            break
    }

In other words, all the || bits are effectively made irrelevant, and your switch statement is really only accounting for four letters.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
1

Actually, getLetter('e') also returns undefined.

    switch(s[0]){
        case 'a': case 'e': case 'i':: case 'o': case 'u':
            letter='A'
            break
        case 'b': case 'c': case 'd': case 'f': case 'g':
            letter='B'
            break
        case 'h': case 'j': case 'k': case 'l': case 'm':
            letter='C'
            break
        case 'n': case 'p': case 'q': case 'r': case 's': case 't': case 'v': case 'w': case 'x': case 'y': case 'z':
            letter='D'
            break
    }

will work as you wanted.

Also, if there is a guarantee that s[0] is alphabet, you can rewrite:

default:
   letter='D'
   break
heartleth
  • 132
  • 7
1

This is not working for any of the other cases as well. it's only evaluating the first case.

If you want to use multiple cases you should do it in this format:

 switch(s[0]){
    case 'a':
    case 'e':
    case 'i':
    case 'o':
    case 'u':
        letter = 'A'
        break;
   case 'b':
   case 'c':
   ...
   ...
        letter = 'B'
        break;
   ...
 }
Ran Turner
  • 14,906
  • 5
  • 47
  • 53