Tinderbox Forum

Gather all values of all $UserAttributes in a Project

Wondering how to approach this.

End goal is to have a Note whose $Text comprises:

$UserAttribute01: (value01, value02, value03…)
$UserAttribute02: (value01, value02, value03…)

$UserAttribute20: (value01, value02, value03…)

Let’s break this up into two parts.

  1. Make a list of user attributes

  2. Given a list of attributes, export a line for each one.

attribute1
attribute2
attribute3

  1. Instead of just exporting the attribute name, export the attribute name, a color, and a list of its values.

And later you can figure out how to extend that to a list of names and values.

So, three steps — each of which is, I think, fairly small. And you don’t have to solve them in sequence; you could start with step 3, then do step 1, and finish with step 2.

1 Like

First, you are doing this because you first tried using Attribute Browser view and it didn’t work? :wink:

This builds off a fairly well-used model of getting a note-per-value for an attribute. So, we:

  • iterate a list of attribute names. for each item (i.re. an attribute):
  • collect a list of its current unique values.
  • sort list if required
  • create a note using the attribute name
  • set $Text of note to the list of its unique values formatted with \n, i.e. a line break between each item

Now you have a container of notes, named as for the attribute (or titled as you like) where each note contains a sorted list of that attribute’s values at the time the code was run. I think you don’t want this running all the time: see again Attribute Browser view.

Did I mention Attribute Browser view? Even if the answer is still the above, likely you’ll have a clearer view of why you want this, for what purpose and how often it should be run (if indeed more than once). I use this listing method a fair amount but only for export purposes, or structurally as a one-off during the analysis phase of qualitative research. For instance, a not for each term/keyword, but only after those terms are now a fixed set. Then I explode the $Text to make a note per value. In that sort of setting the per-value notes can then link to (or store info for) notes that use that value.

Another tip: if keeping these value-list notes for more than the short term consider setting $Searchable to false (the non-default setting). That avoids terms in $Text being matched in queries and possibly polluting the value lists of some of the attribute you are reporting upon.

1 Like

I’ve not built out the note creation part (free time!) but most of the rest is here. I’ve exposed some ‘hidden’ code—OnAdd, DisplayExpression, etc.—via Displayed Attributes. I’ve also used a scoped values() call to only collect $MyString and $MyList values from notes inside /Stuff.

The two initial value listings are made by running each of the first two stamps on note /Stuff. Note that values() gives back a Set so the values are de-duped. The value listing notes report their discrete item count via Display Expression (count set by the creating stamp).

Two additional stamps explore issues of case-sensitivity and sort order.

You could explode the value listings if you wanted a note per unique source value here I copied note (MyString values) and exploded it using defaults.

I’ve also made a simple Attribute Browser view for $MyString and $MyList. Notice what happens if you change the ‘container’ pop-up from ‘/Stuff/’ to ‘entire document’. Also see the AB view offers counts of the number of notes using that value. See that for Lists/Sets, the occurrence count may be greater than the number of notes as notes list separately under each discrete value that they have. Often a quick AB view is way quicker to just ‘see’ all values for an attribute compared to all the mis-en-plce needed for the above.

Here is the TBX: get-attribute-values.tbx (114.0 KB)

I hope that gives some ideas.

1 Like

OK amazing!! I see the logic behind it and an going to apply the lessons learned in recent weeks to build this… thank you, @eastgate!

Love this, also!! And thanks for the perfect suggestion of toggling $Searchable :ok_hand:t4: - I’ll use that in several utility Notes I keep around in each Project ~

On Attribute Browser - I would if I were working with these values; however the exercise at hand is to cull around 20 User Attributes from a project that needs to be re-structured. I’ll dump the values to Notes, then pull the abandoned UAs. The UA-per-Note approach will be great for that, perfect!

1 Like

Wow, floored!! Thanks @mwra :pray:t4:

1 Like

In which case you may be able to do some work en route to making the $Text-based lists. Look at List/Set.intersect(set) — the article covers both list intersect, i.e. items in both lists A and B, and non-intersect i.e. in A or B but not in both A and B.

You can also add Lists or Sets, to aggregate them, remembering to de-dupe if using List-type as the collecting type. Lowercasing everything also lessens the chance of an apparent non-overlap of usage that is only due to lettercase. As long as you are only using copies of the source info, the lowercasing is non-destructive to the actual source.

Whilst the hood is up on this, also scan for close matches. This more a human task than a code one. I find when doing this sort of task, taking a moment to scan-read the initial listings primes my memory to spot that ‘lion’ here is ‘cat’ there and adjust accordingly if needed.

Aside, I should have added that values() returns a set of unique values occurring (in scope—default whole doc) for that attribute. So the output Set-type data is de-duped case-sensitively. To de-dupe further:

$MyList = value("SomeAttribute").lowercase.sort.unique;

Why use a List at left and not a Set? Lists don’t re-sort themselves, so give more control going forward. If, as here, you know there are no dupes, Lists thus offer more flexibility—but the user always has the choice.

HTH. This sort of task is a PITA (my research involves a lot of this) even if the outcome is good.

†. That’s the list matching. The pain I could do without. :slight_smile:

1 Like

Great, the .intersect operator seems fantastically useful when one thinks of the applications. Inspired by all this great input, and intending to make a usable/shareable toolkit of it :slight_smile:

1 Like

I use this all the time. It is fantastic for creating a list of key terms referred to on branches in a document, e.g., give me a table of all the key terms that are descendants of a particular note. I use this approach in my client reports and key terms for chapters in the textbooks and courses I write.

1 Like

How exactly? Are you polling Attributes of descendants using intersect? Or Tagger/Highlighter to extract key terms from $Text, then generating intersect(set) of target Attributes thus populated?