Tinderbox v9 Icon

List/Set.contains("pattern")


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]

 Baseline

 


List.contains("pattern")

This operator tests whether pattern matches a whole discrete value string within the referenced 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:

An always case-insensitive option is offered via List/Set.icontains() though it too cannot match below list item granularity.

pattern is one of:

$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") 

$MyList(parent).contains("Tuesday") 

are both true if $MyList contains "Monday;Tuesday;Friday". A match can use a attribute value as the pattern. Consider a single-value String-type attribute 'MyDay':

$MyList.contains($MyDay) 

is true if the value of $MyDay for a given note is any of "Monday", "Tuesday or "Friday". Thus in an agent or find query, the pattern varies by the source value in the currently-tested note.

The chained list may also be a literal list:

"Saturday;Sunday".contains("Sunday") 

"Saturday;Sunday".contains($MyDay) 

If the pattern is found the function returns the matched list position (1-based). Formerly, .contains() returned true if the pattern was found.

Testing "does not contain"

Use a ! prefix to the query argument:

!$MyList.contains("Tuesday") 

Use of parentheses after the !, around the query, can assist Tinderbox's parsing:

!($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 will not be good if the supplied 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

It is possible to use a semi-colon join but it seems to tempt a parsing error, given that a semicolon is Tinderbox's list delimiter. The above result means that .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.

Using .contains() to test individual value equivalence to a String

See == (equality) testing.