# Conditional Scripting/Expressions

Hi guys, looking for opinions if you’d be so kind! I’m trying to figure out the best way to write an expression that would produce a string value based on the following dataset of conditions:

Based on the conditions from the first four columns on the left, I want to produce the “Selected Option” displayed in the same row on the far right.

I started on a huge string of if statements but the complexity of the “ifs” is leading me to believe there is much simpler way to do this that I just haven’t discovered yet.

What would you guys do?

A case statement would be easier than going with ifs.

Edit: Actually that might not work for your use.

When I set up scenarios for similar situations I have a somewhat complicated solution I fall back to because it works.

It looks like you have the wonderful luck of having four columns with binary values (`0`/`1`, and “Good”/“Bad”). Mentally convert all of those values to actual binary bits:

``````0 -> 0
1 -> 1
"Good" -> 1
``````

Now you can represent each row as a four-bit binary value, ie row `0` becomes `0101`.

Now, instead of having to do conditionals to determine the what to do for each branch you can indeed fall back to a switch statement, or you could just use a Python dictionary:

``````tags = system.tag.readBlocking(["pathOne.value", "pathOne.quality", "pathTwo.value", "pathTwo.quality"])
opt_1_val = tags[0]
opt_1_qual = tags[1]
opt_2_val = tags[2]
opt_2_qual = tags[3]
converted = "".join([str(opt_1_val), "1" if opt_1_qual == "Good" else "0", str(opt_2_val), "1" if opt_2_qual == "Good" else "0"])
value_map = {
"0101": "Option 1",
"1111": "Option 2",
"0110": "Option 1"
}  # and include the rest of the valid options
return value_map.get(converted, None)  # None if map contains no match
``````

The downside is the map requires maintenance when requirements change (like added return values or changes to what each four-bit value represents), but it prevents long, branching if statements.

1 Like

I would move the boolean logic into here instead of into the join. I think you also still need the `.value` as well, so I would instead just read the 2 tags:

``````from com.inductiveautomation.ignition.common.model.values import QualityCode
tags = system.tag.readBlocking(["pathOne", "pathTwo"])
options = []
for tag in tags:
options.append(tag.value)
options.append(tag.quality.level == QualityCode.Level.Good))

converted = "".join({True: '1', False: '0'}.get(option, '0') for option in options)
``````

Maybe using QualityCode here is overkill…

Great thinking! I’m going to give that a shot today. Thanks so much!

Very cool idea! I will look into this today as well! Thanks @nminchin !

I would just use

``````options.append(tag.quality.good)
``````
1 Like

@josborn I looked at using a case statement as well but it seemed equally as cumbersome as the if statement scenario! Thanks for the reply!

A switch statement is actually a lot cleaner than even the map because you can fall through similar cases, so you’d actually only need four or five definitions.

``````# not perfect syntax, but the gist is this:
switch (converted): {
case "0101":
case "0110":
case "0111":
case "1001":
return "Option 1"
case "1111":
case "0011":
case "1101":
case "1100":
return "Option 2"
case "0011":
case "1000":
return "Lad Good Option"
default:
return "option not mapped"
}
``````

Edit: I’m not really sure the correct Jython syntax. Python doesn’t support switch statements - they’re a Java concept - but Jython doesn’t require semi-colons, so… maybe this will work as-is? And since we’re returning we don’t need `break`.

1 Like

@cmallonee Nice!!

No, it won’t. The pythonic structure is `if-elif-elif-else`.

You could always use a dictionary with a `.get()` but since there’s so many cases with the same output I think the easiest way would be

``````# assume we have converted variable that is the 4 digit string
case_1 = converted in ["0101", "0110", "0111", "1001"]
case_2 = converted in ["1111","0011","1101","1100"]
case_3 = converted in ["0011","1000"]

if case_1:
return "option 1"
elif case_2:
return "option 2";
elif case_3:
return "option 3"
else:
return 'option not mapped'
``````

Ah, so Jython doesn’t support switch statements at all? That’s too bad.

The python equivalent to switch statements, Match statements, were only just introduced to python 3.10 IIRC

Here’s a link to all of the alternatives we’ve covered here. As @bkarabinchak.psi pointed out, the match case is not available in Ignition because we’re not using Python 3.10.

I would not compute case_1, case_2, and case_3 ahead of the if-elif-elif-else block. Compute in the `if` block. Put the most likely condition first. The other computations will be skipped.

I was trying to put all of this in an expression tag, but haven’t had luck making it work yet with all of your great suggestions… Should I maybe be trying to place all of this somewhere else? Would all of this be better suited as a script instead of an expression?

All of the examples given so far use scripting. You could use `binEnc` and `case` to do something similar entirely with expressions, but the logic becomes (arguably) more difficult to reason about:

``````
case(
binEnc(
{Tag1},
{Tag2},