# How to simplify ternary expressions in Javascript

I have an expression that could be expressed as either of :

a += (A ? B ? x : C ? y : D : D);

a += (A && B ? x : A && C ? y : D);


where A,B,C are expressions of 5-10 bytes each, and x and y are single character literals (3-4 bytes). D is another chain of ternaries (without the branching problem).

I'm getting stuck trying to eliminate the duplication of D or A. If I was using if, it would be something like this:

if (A)
if (B)
x
else if (C)
y
else D


Obviously I could do ((z=A) && B ? x : z && C ? y : D)...but any other more creative suggestions?

The actual code looks something like:

if (r%4<2&&r>3&&c<22&&c>1)
if ((i-r)%8==6)
'\\'
else if ((i+r)%8==1)
'/'
else


D is something like:

(i+r) % 8 == 3 ? '/' :
(c-r+16) % 8 == 4 ? '\\' :

• It would help to know what those expressions are. May 18, 2017 at 3:57
• yup, updated. try not to distracted by golfing them :) May 18, 2017 at 3:58
• Well, (i-r)%8 can become i-r&7 :p May 18, 2017 at 3:59
• I still can't see what your D is. May 18, 2017 at 4:00
• Updated again... May 18, 2017 at 4:01

If you know that x and y cannot contain falsy values, as your code examples suggest, you can do the following to eliminate duplicate evaluation of A or D:

a += A && (B && x || C && y) || D;


Demo code and test cases in the following snippet:

// return x
test(1,1,0); // A and B
test(1,1,1); // A and B (and C)

// return y
test(1,0,1); // A and C

// return D
test(0,0,0); //
test(0,0,1); // C
test(0,1,0); // B
test(0,1,1); // B and C
test(1,0,0); // A

function test(A, B, C) {
var x = 'x', y = 'y', D = 'D';
a = A && (B && x || C && y) || D;
expected = (A && B ? x : A && C ? y : D);
var ws = ' ';
console.log(
[
A && 'A' || ws,
B && 'B' || ws,
C && 'C' || ws
].join(ws),
' ==> a = ' + a,
a === expected ?
'Passed' :
'Failed, expected ' + expected
);
}

Otherwise, if falsy values are possible, you could do this:

a += [D, x, y][A && (B && 1 || C && 2) || 0];


Demo code and test cases in the following snippet:

// return x
test(1,1,0); // A and B
test(1,1,1); // A and B (and C)

// return y
test(1,0,1); // A and C

// return D
test(0,0,0); //
test(0,0,1); // C
test(0,1,0); // B
test(0,1,1); // B and C
test(1,0,0); // A

function test(A, B, C) {
var x = false, y = 0, D = '';
A = !!A; B = !!B; C = !!C;
a = [D, x, y][A && (B && 1 || C && 2) || 0];
expected = (A && B ? x : A && C ? y : D);
var ws = ' ';
console.log(
[
A && 'A' || ws,
B && 'B' || ws,
C && 'C' || ws
].join(ws),
' ==> a = ' + xyD(a, x, y, D),
a === expected ?
'Passed' :
'Failed, expected ' + xyD(expected, x, y, D)
);
}

function xyD(result, x, y, D) {
return result === x ? 'x' :
result === y ? 'y' :
result === D ? 'D' : '<error>' ;
}

• Thanks, that's very helpful. So, probably I should just stop thinking in terms of ternaries altogether. Jun 12, 2017 at 22:23

Since short-circuiting is not required here, you can also do:

d=D;a+=A?B?x:C?y:d:d;


If short-circuiting were required, since your B and C are truthy values, you can do:

a+=(A?B?x:C?y:0:0)||D;


If short-circuiting were required and your B and C are not truthy values:

d=_=>D;a+=A?B?x:C?y:d():d();

• Ah, that second one is an interesting way to "fall through" a ternary operator. May 18, 2017 at 4:25