Best way to display different strings based on given combination?

Hi guys, let's say I have variable a, b, c having 0 or 1 values. I want to display a string, based on the given combination, like this:

a = 0, b = 0, c = 0 -> value: "message 1"
a = 1, b = 0, c = 0 -> value: "message 2"
a = 1, b = 1, c = 0 -> value: "message 3"

What is the best way for this in javascript?

The most straightforward way I can think of is to use a lookup object:


function lookupMessage(a: number, b: number, c: number) {
    
    const key = `${a}${b}${c}`
    
    const messages = {
        "000": "Message 1",
        "100": "Message 2",
        "110": "Message 3"
    }
    
    return messages[key]
}

Would that work?

1 Like

Hi @Rupur ,

I set up a JS Query with the code below and it worked fine.

const messages = {
  "000": "message 1",
  "100": "message 2",
  "110": "message 3",
  // Add more cases as needed
};

// Get values from Retool components
const a = Number(aInput.value); // Example: Get value from a text input
const b = Number(bInput.value);
const c = Number(cInput.value);

const key = `${a}${b}${c}`;
return messages[key] || "Default message"; // Return message or fallback

@torin's function looks good too

1 Like

@torin @Shawn_Optipath

Hi guys, thanks for the fast help.

I was wondering if there is a way for wildcard values as well?

Like a = 0, b = 0 or 1, c = 0 -> 'message 4'?

If I understand the question correctly, that's what the || "Default Message accomplishes in @Shawn_Optipath's solution.

If a set of incoming values does not match a key in the lookup table, it'll return a default.

No I mean I want for example message 2 to display if value a is 1 and value c is 1, the value of b is irrelevant.

Otherwise I would need to write a message for each possible combination like

101: message 2
111: message 2

I was wondering if something like

1*1: message 2 is possible

Hey @Rupur,

This is giving me some flashbacks to logic gates and truth tables from long long ago. Since you are talking about 0 or 1 values you could probably write some case logic for this:

In your example, message2 would result from the condition a && c.
In your message 4 example, it would be the condition !a && !c.

Mapping your 0s and 1s to true/false comparisons would still require you to write the logic for the proper combos, but you could maybe then start to generalize the right pattern for all of your cases. You also might need to consider some logical precedence for case (like only a which would need to take precedence over a or b if that distinction was required).

I don't know how many options you have or if they are meant to be dynamic, but you could definitely reduce the total number of permutations this way.

Some clunky code:

let groupData = {{  checkboxGroup1.values }}
let selectedData = {{ checkboxGroup1.selectedItems }}
let message = "DEFAULT MESSAGE BEFORE RUN"
let options = groupData.map(option => {
  return { 
    option: option, 
    optionValue: selectedData.some(selection => selection.value === option)
  }
})


switch (options.length > 0){    
  case options[0].optionValue && options[2].optionValue:{ 
    message = "1 AND 3";
    break;
  }
  case options[0].optionValue && (!options[1].optionValue && !options[2].optionValue) :{
    message = "1 ONLY";
    break;
  }
  case options[0].optionValue || options[1].optionValue: {
    message = "1 OR 2";
    break;    
  }
  default: 
    message = "Default after run."
    break;
}

return message

Just a logical proof of concept using a checkbox group:
image

2 Likes

I took a crack at this using regex. There are definitely cleaner ways to do it with regex patterns, especially if you needed to expand to more than 3 characters, but this was the most straightforward way I could come up with.

There are also definitely more clever and more performant ways to do this, like with bit masks, which would be worth investigating.

function lookupMessage(a: number, b: number, c: number): string {
    const key = `${a}${b}${c}`;

    const patternMap = [
        
        // Exact matches
        { regex: /^000$/, message: "message 1" },
        { regex: /^100$/, message: "message 2" },
        { regex: /^110$/, message: "message 3" },

        // Wildcard matches
        { regex: /^10[01]$/, message: "a=1, b=0, c=any message" }, // 100 and 101
        { regex: /^11[01]$/, message: "a=1, b=1, c=any message" },   // 110 and 111

    ];

    for (const { regex, message } of patternMap) {
        if (regex.test(key)) {
            return message;
        }
    }

    return "Default message";
}
2 Likes

What a fun thread :smiley:

2 Likes

I love seeing what other people come up with. There are a hundred ways to cook an egg. :fried_egg:

3 Likes

How about using wildcards as per your suggestion?

const messages = [
  { pattern: "0*0", message: "message 4" }, // Wildcard first!
  { pattern: "1*1", message: "message 2" }, // Wildcard first!
  { pattern: "000", message: "message 1" },
  { pattern: "100", message: "message 2" },
  { pattern: "110", message: "message 3" }
];

// Function to find the matching message
const getMessage = (a, b, c) => {
  const key = `${a}${b}${c}`;
  console.log(`Checking for key: ${key}`);

  // Find the first pattern that matches the key
  const match = messages.find(({ pattern }) => {
    console.log(`Testing against pattern: ${pattern}`);
    return key.split("").every((char, index) => 
      pattern[index] === "*" || pattern[index] === char
    );
  });

  console.log(`Matched pattern: ${match ? match.pattern : "None"}`);
  return match ? match.message : "Default message";
};

// Example test cases
console.log(getMessage(0, 0, 0)); // "message 4" (wildcard 0*0 should match first)
console.log(getMessage(1, 0, 0)); // "message 2"
console.log(getMessage(1, 1, 0)); // "message 3"
console.log(getMessage(0, 1, 0)); // "message 4" (wildcard 0*0 should match first)
console.log(getMessage(1, 0, 1)); // "message 2" (wildcard 1*1 should match first)
console.log(getMessage(1, 1, 1)); // "message 2" (wildcard 1*1 should match first)
2 Likes

I hope this has been helpful, @Rupur! It's great to see so many suggestions. :slightly_smiling_face: