Collecting $Tags values - what am I doing wrong?

Hi All - trying to collect all $Tags values in my project as a set, but for some reason I get a list.

I tried both:

// after creating an Attribute “$TagList” of type “set”

== and alternatively ==


== and, more directly ==


But my $Text contents are a list type. Where am I erring?


What exactly do you mean here?

Technically, your $Text contents are of text type, because $Text is a text attribute.

$Text is a String-type attribute. What do you mean by “contents are a list type”? collect() returns List-type data, but if you pass it’s output into a Set attribute, you have a Set. In practical terms, having Set implies having a case-sensitive de-duplicated list (small ‘l’), lexically sorted A–Z.


Is there a reason for using collect() which is documented as returning a List instead of values() which returns at Set. Surely the latter is what you actually want?

Though collect() goes back a long way, values()was added in v5.10.1 specifically for this task: getting the unique (case-sensitive) set of values for a given attribute, whether single or multi-value attribute. Originally whole document scope, an option to scope values() to only part of the document was added in v7.0.0.

Of course, you can use collect() but to get a set, you must pass its output into a Set-type attribute as per the third of your examples above.

1 Like

Ah ok, thanks for steering me right! Will switch to values(). I didn’t recall this distinction and was running on the assumption that using collect() to gather values within a set-type Attribute would suffice. That’s evidently not the way to go about it, then.

I could re-do it and check, but none of my examples served to strip the list down to a set.


For long-time players, there is some back-story. Way, back collect generated Set data, in no small part because List-type only arrived in v5.6.0. At that point collect() shifted from Set output to List output.

However, I think these two are functionally equivalent ways of getting a unique listing of values used across the current TBX in $Tags:

$Text = values("Tags").format("\n");
// or
$Text = collect(all,$Tags).unique;
// note the two give a different sort
// ... you could put a '.sort()' before the dot-format

If you don’t want case variants, not both ‘ant’ vs. ‘Ant’, lowercase the values:

$Text = values("Tags").lowercase().sort().replace(";","\n");
// or
$Text = collect(all,$Tags).lowercase().unique().sort().replace(";","\n");

Note, as I’m manipulating a listing without going through a Set (attribute or variable), the lowercase() command turns a listing into a string. Thus the use of String.replace() not list.format().

Of course, there are always alternates, the last values() example above, can be done this way, using explicit Set-type data:

var:set vSet = values("Tags").lowercase();
$Text = vSet.format("\n");
1 Like