Alternative to nested ternary operator in JS
Your alternatives here are basically:
- That
if
/else
you don't want to do - A
switch
combined withif
/else
I tried to come up with a reasonable lookup map option, but it got unreasonable fairly quickly.
I'd go for #1, it's not that big:
if (res.distance == 0) { word = 'a';} else if (res.distance == 1 && res.difference > 3) { word = 'b';} else if (res.distance == 2 && res.difference > 5 && String(res.key).length > 5) { word = 'c';} else { word = 'd';}
If all the braces and vertical size bother you, without them it's almost as concise as the conditional operator version:
if (res.distance == 0) word = 'a';else if (res.distance == 1 && res.difference > 3) word = 'b';else if (res.distance == 2 && res.difference > 5 && String(res.key).length > 5) word = 'c';else word = 'd';
(I'm not advocating that, I never advocate leaving off braces or putting the statement following an if
on the same line, but others have different style perspectives.)
#2 is, to my mind, more clunky but that's probably more a style comment than anything else:
word = 'd';switch (res.distance) { case 0: word = 'a'; break; case 1: if (res.difference > 3) { word = 'b'; } break; case 2: if (res.difference > 5 && String(res.key).length > 5) { word = 'c'; } break;}
And finally, and I am not advocating this, you can take advantage of the fact that JavaScript's switch
is unusual in the B-syntax language family: The case
statements can be expressions, and are matched against the switch value in source code order:
switch (true) { case res.distance == 0: word = 'a'; break; case res.distance == 1 && res.difference > 3: word = 'b'; break; case res.distance == 2 && res.difference > 5 && String(res.key).length > 5: word = 'c'; break; default: word = 'd'; break;}
How ugly is that? :-)
To my taste, a carefully structured nested ternary beats all those messy ifs and switches:
const isFoo = res.distance === 0;const isBar = res.distance === 1 && res.difference > 3;const isBaz = res.distance === 2 && res.difference > 5 && String(res.key).length > 5;const word = isFoo ? 'a' : isBar ? 'b' : isBaz ? 'c' : 'd' ;
You could write an immediately invoked function expression to make it a little more readable:
const word = (() => { if (res.distance === 0) return 'a'; if (res.distance === 1 && res.difference > 3) return 'b'; if (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) return 'c'; return 'd';})();