In an alarm Display Path binding, I want to use the folder name 2 parents below where the alarm resides, but am struggling to find information about how to do this. I can’t see a way to get the number of rows in a dataset using the expression language.
e.g. alarm tag path:
Winery/Receivals/Crushers/DC2001/Flush Valve/Alarms/Failed to Open
I’d like the display path to be:
‘Crusher 1 Flush Valve Failed to Open’
which means pulling out ‘Flush Valve’ from the tag path. I would like the expression to be as re-usable as possible so that I can use it in any location, and fix itself if ever the parent device folder (e.g. DC2001) is moved.
So far I have:
split({itemPath}, ‘/’)[row,0]
where ‘row’ needs to be replaced with psuedo-code (count-3) (’-3’ as index starts at 0)
The expression function len() (somewhat confusingly, placed in the ‘Strings’ section) works directly on datasets - so you can work backwards from the number of rows that way.
I just ran into a similar issue but I only wanted the last part of the tag path. I ended up using a lambda inside the runScript expression function. For anyone in the future this is what I used and it makes passing in arguments clear:
Be aware that invoking a script is less performant than using an expression. Although the expression is more awkward, it has a lot less overhead in the gateway. Always favour expressions over scripts
As @nminchin said, I think you'll find this expression to be more performant. Just have to remember that the regex pattern in the split expression is selecting what will be removed from the string.
I've never been real happy with how expressions deal with common sub-expressions. That is, not happy at all. The impetus to find a solution isn't there in Perspective, because you can put such expressions ahead of a transform so they will only be executed once. (And if you have more than one, my new asList() expression can bundle multiple such into a single value.)
But expression tags and Vision UI bindings do not have transforms.
I realized while reading this topic that I've already created a combination that can do this, and using len() on the result of split() is the perfect test case:
The split() in the center of this expression is executed once, the result dataset becomes the one element in a list to be iterated, and therefore handed to both calls to it() within the loop (which runs just the once) to build the output list. Take the one element of that output list as the final output.
Yielding the last element of the path, but only referencing the string property once, and only running split() once.