Tinderbox Forum

Syntax: Matching multiple values of an attribute

Hi,

Is there any shortcut syntax for queries / conditionals of the type:

$SomeAttribute=="X" | $SomeAttribute=="Y" | $SomeAttribute=="Z"

E.g. something like:

$SomeAttribute == {"X" | "Y" | "Z"}

…where you don’t have to repeat the left hand side of the query? I’ve looked in the help, in the forum and in atbref, but $Answer=="No" | $Answer=="I'm not using the right search terms", so forgive me if this is covered somewhere.

TIA.

1 Like

How about this:

$MySet.contains($SomeAttribute)

where $MySet is "X;Y;Z;?

In short, No. (not that I too, wouldn’t like such a shorthand method)

If you find yourself searching multiples a lot, I find it easier to add metadata as a tag or a user Boolean or such to allow one query term to find all desired matches.

Am I correct this is about writing ‘shorter’ code or is the a nested question here?

1 Like

Thanks for the quick replies.

Mark A:

It’s essentially to stop typing $Prototype== several times… you’re right I could use some form of meta marking. I just wondered whether there a method built into the syntax.

Mark B:

Thanks for your suggestion: sorry if my example was too generic, but is there a way the set approach you outline could work with multiple $Prototype== calls in a query?

Thanks!

Sure.

  1. Make a note – say a top-level note named InterestingPrototypes.
  2. Set $MySet of InterestingPrototypes to the list of your interesting prototypes — perhaps “Task;Project;MaybeSomeday”
  3. In your agent, the query becomes
     $MySet(/InterestingPrototypes).contains($Prototype)
3 Likes

That works perfectly — thanks very much!

I didn’t know you could use .contains plus an $Attribute name in that way.

I’d assumed that contains simply tested whether a value was in the set, but this seems to imply that the elements are further plugged into an $Attribute== expression. Is that right or is there something I’m missing?

If so it’s using contains in a way that I didn’t realise was possible — but whether I understand how it works or not, it does and it’s very useful!

Thanks again.

to clarify, when using a List or Set with .contains(pattern), pattern is one of:

  • an action code expression (which includes just referencing a single attribute name’)
  • a quoted literal string (i.e. actual text). Important : do not omit the enclosing quotes. If omitted, Tinderbox will try to evaluate the string as an expression. Doing this may result in the expected result but this is actually a false positive. So, remember to enclose your literals in quotes.

As the first bullet explains, an expression can be as simple as a single attribute reference, e.g. $Prototype.

2 Likes

Thanks Mark,

I knew that contains can match a pattern, including single attributes: what I wasn’t aware of was that the result is a query which in effect turns the expression on its head, so that in practice (not in syntax!) it’s:

$Prototype == (any element in MySet).

In other words — I didn’t know the syntax doesn’t just find the values of $Attribute, but that it also uses those values in a series of queries on that attribute.

I didn’t get that implication from the atbref text, which is probably my fault. I know you’re very busy, but would it be worth adding a note to the atbref text?

E.g. after

$MyList.contains($MyDay)

In an Agent Query, this would return all notes where $MyDay is one of “Monday”, “Tuesday” or “Friday”.

Thanks again.

OK, I’ve updated the List/Set.contains() (and .icontains(), appropriately edited) to this:

$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.

Does that help

1 Like

Thanks!

1 Like