flow24
flow24

Reputation: 943

Converting multiple if statements to ternary (JavaScript)

Given this block of statements:

let chosenMachine;
if (bubbleDetailsObject.names.includes(machineName)) chosenMachine = bubbleDetailsObject
if (primoDetailsObject.names.includes(machineName)) chosenMachine = primoDetailsObject
if (familyDetailsObject.names.includes(machineName)) chosenMachine = familyDetailsObject

How can I convert them to a one-line ternary statement?

Upvotes: 1

Views: 147

Answers (5)

LHM
LHM

Reputation: 889

Well, this is how you could do it with ternaries (granted this is not one ternary, but then your code does not contain only one if) , but this is not recommended for reasons that others have mentioned (i.e. lack of readability and maintainability)...

let chosenMachine = 
    familyDetailsObject.names.includes(machineName)
        ? familyDetailsObject
        : primoDetailsObject.names.includes(machineName)
            ? primoDetailsObject
            : bubbleDetailsObject.names.includes(machineName)
                ? bubbleDetailsObject
                : undefined;

Note the reverse order of Objects to ensure that the precedence is maintained, since any number of the if statements could be true.

An easier to read implementation might be something like:

const detailsObjects = {
    bubbleDetailsObjects: { names: ["..."] },
    primoDetailsObjects: { names: ["..."] },
    familyDetailsObjects: { names: ["..."] }
}

let chosenMachine; 

Object.keys(detailsObjects).forEach(key => {
    chosenMachine = 
        detailsObjects[key].names.includes(machineName)
            ? machineName
            : chosenMachine;
})

This gives you a single ternary statement while also preserving your original objects.

Upvotes: 0

Peter Wone
Peter Wone

Reputation: 18815

Ternary operations can be nested by the simple expedient of delimiting sub expressions with parentheses

let result = (condition 1) ? (expr 1) : (expr 2);

Either of the expressions can itself be a ternary expression, and the parentheses resolve all the syntactical ambiguities.

let result = (condition 1) ? ((condition 2) ? expr 3 : expr 4) : (expr 2);

However, this approach will produce code that is difficult to read and very inconvenient to debug. Even in this very simplified pseudocode the line is quite long.

Given that you are progressively testing set intersection rather than simple equality I'd be inclined to leave your original code as is.

Upvotes: 0

luiscla27
luiscla27

Reputation: 6469

Ternaries are supposed to return a single value, In your code the 3 if's can be true when machineName exists inside the three objects, assuming thats unintended, your ternary should look like this:

const chosenMachine = bubbleDetailsObject.names.includes(machineName) ? bubbleDetailsObject : primoDetailsObject.names.includes(machineName) ? primoDetailsObject : familyDetailsObject.names.includes(machineName) ? familyDetailsObject : null;

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 371193

If possible, I'd change around the structure of your variables so that those objects are enclosed in another object or array, maybe something like:

const detailsObjects = {
  bubble: {
    // ...
  },
  primo: {
    // ...

This will both make your code more organized, but it'll also let you identify the matching object more concisely by iterating over the values, rather than having to deal with multiple similar standalone variables:

const chosenMachine = Object.values(detailsObjects)
  .find(obj => obj.names.includes(machineName));

Upvotes: 2

blex
blex

Reputation: 25648

Without ternary statement (which might be harder to read when they're nested):

const chosenMachine = [familyDetailsObject, primoDetailsObject, bubbleDetailsObject]
                      .find(o => o.names.includes(machineName));

Upvotes: 2

Related Questions