Operator Type:
Operator Scope of Action:
Operator Purpose:
Operator First Added:
Operator Altered:
Function [other Function type actions]
Item [operators of similar scope]
Query Boolean [other Query Boolean operators]
5.7.0
5.10.2
List.contains("pattern")
This operator tests whether pattern matches a whole discrete value string within the target list/set attribute. Unlike with string attributes matches using String.contains(), matches are always case-sensitive and cannot be overridden with $AgentCaseSensitive. The match gives a Boolean result.
Thus in default settings, List/Set.contains is always:
- case-sensitive in an agent (unlike a String attribute $AgentCaseSensitive is ignored)
- case-sensitive in all other action code contexts
An always case-insensitive option is offereed via List/Set.icontains() though it too cannot match below list item granularity.
pattern is one of:
- an action code expression (which includes just referencing a single attribute name')
- a quoted literal string (i.e. actual text)
$MyList.contains("pattern")
The contains operator may also be used with both sets and lists, in which case it tests for set membership, i.e. matching to complete individual values rather than part of values. Thus:
$MyList.contains("Tuesday")
is true if $MyList is "Monday;Tuesday;Friday". Other examples:
$MyList.contains($MyDay)
$MyList(parent).contains("Tuesday")
The left-hand argument may also be a literal list:
"Saturday;Sunday".contains($MyDay)
From v5.10.2, if the regular expression pattern is found the function now return the match's offset+1, where offset is the distance from the start of the string to the start of the matched pattern. Formerly, .contains() returned true if the pattern was found. The '+1' modifier ensures that a match at postion zero return a number higher than zero which would otherwise coerce to false. Since 1+offset is always true, no changes are required in existing documents but the function also now gives usable offset information.
Testing "does not contain"
Use a ! prefix to the query argument:
!$MyList.contains("Tuesday")
Testing lists values for partial matches
Used with care, there is a workaround by mimicking the way .replace() works with lists - see the section on regex. The trick is to use an on-the-fly list-to-string coercion allowing all list values to be regex-matched as if a single string. This is achieved by chaining List.format.contains. In order not to confuse the regex, the .format() join string should be a simple (ASCII) printable symbol that has no regex meaning. A hash (#) is a good example - though clearly this won't be good if the target list values include hash symbols! therefore you may need to alter the join symbol depending on your data.
Tinderbox stores a list of values, like ant/bee/cow/dog/eel, as a single semi-colon delimited string "ant;bee;cow;dog;eel
". So, for that list:
$MyList.format("#")
returns "ant#bee#cow#dog#eel
"
Possible a semi-colon join could be used but it seems to be tempting a parsing error. The above result now means .contains() works as if doing a String.contains() test.
For the same data as above, these are effectively the same thing, albeit the first using a string literal:
"ant#bee#cow#dog#eel".contains("ee#|ee$;")
$MyList.format("#").contains("ee#|ee$")
In either case, .contains returns true, but would return false if 'bee' were removed. This is because the regex pattern only matches a double-e substring at the end of a value.
Until/unless Tinderbox's List.contains() directly supports substring matching within list values, the above offers a workaround.
Dealing with inline quote characters
Because pattern is parsed for regular expressions, it may be possible to use the '\dnn' form described here to work around the lack of escaping from single double quotes within strings.