Tinderbox Forum

Creating a Dictionary Lookup for an attibute value?

I seem to be getting stuck creating my first dictionary lookup item.

I have an attribute called $HighlightColor with one of several values

Example
Device RGB colorspace 1 1 0 1 = yellow
Device RGB colorspace 1 0.5 0 1 = orange

I have created a custom attribute Dictionary named $ColorDictionary

Here is the code for the function i used (which may not be right, this is my first attempt at creating a function and using a dictionary)

function fColorDictionary(input){
$ColorDictionary=$ColorDictionary("Device RGB colorspace 1 1 0 1:yellow;Device RGB colorspace 1 0.5 0 1;orange ")
}

Goal: I am trying to create a lookup for my $HighlightColor to lookup and replace the RGB color value with its corresponding color

I am not sure how to link the two. I am hoping to create an edict within a prototype called pRdNote

TestingColorDictionary.tbx (599.1 KB)

Thanks in advance
Tom

Several immediate points stand out…

Creating the dictionary. You have created a used dictionary attribute $ColorDictionary. But you haven’t set it. This

$ColorDictionary=$ColorDictionary("Device RGB colorspace 1 1 0 1:yellow;Device RGB colorspace 1 0.5 0 1;orange ")

…is setting the entire value of $ColorDictionary for the note calling your function to the value of the same attribute whose $Name, improbably is "Device RGB colorspace 1 1 0 1:yellow;Device RGB colorspace 1 0.5 0 1;orange " (even down to the trailing space!). No matter, I think what you meant to use was (note the corrected ; to : in the second term):

$ColorDictionary=dictionary("Device RGB colorspace 1 1 0 1:yellow;Device RGB colorspace 1 0.5 0 1:orange ")

i.e. using the dictionary() action operator to make Dictionary-type from the supplied string—which of course is actually supplied as a list of value:key; pairs.

So not the function populates $ColorDictionary of the note calling the function with two key:value pairs: Device RGB colorspace 1 1 0 1:yellow; and Device RGB colorspace 1 0.5 0 1;orange. Still not really helping.

We either want to store this dictionary in the $ColorDictionary of a single specific note or make a dynamic Dictionary-type variable inside the function and access values via function input, i.e. a look-up wrapper.

Using an attribute

I’ll assume we’ve a note called “_config” (i.e. at $Path /_config) to hold the data. Where you put such a note and what you call it matters not except do make the name unique (thus my use of an underscore prefix), making it addressable via $Name alone. Obviously, if differing the title adjust example code below accordingly. We’ll make a Stamp “Set Colour Dictionary”, and assume it has all the key:value; data needed:

$ColorDictionary=dictionary("Device RGB colorspace 1 1 0 1:yellow;Device RGB colorspace 1 0.5 0 1:orange ");

We use it to stamp our “_config” note. I see from the demo that data notes store the dictionary’s key values on their $HighlightColor:

So for the above note to correctly get the colour value of the key “Device RGB colorspace 1 0.5 0 1” it would call this code:

$MyString = $ColorDictionary("_config")["Device RGB colorspace 1 0.5 0 1"];

Tada!:

or, via the value of $HighlightColor:

$MyString = $ColorDictionary("_config")[$HighlightColor];

Using a function

We can employ a function() to store the dictionary. Here’s our function, commented to show how:

function fColorspaceLookup(iDevice){
   // iDevice is a string input with a dictionary key value  

   // Define a Dictionary-type variable
	var:dictionary vColorDict;
   // store device-colorspace:color key:value pairs as needed
   vColorDict.extend("Device RGB colorspace 1 1 0 1:yellow;");
   vColorDict.extend("Device RGB colorspace 1 0.5 0 1:orange;");
   // dictionary now complete

   // return the colour value matching iDevice
   return vColorDict[iDevice]
}

I know I’m adding key:value pairs one at a time but there may be many and they may change over time. this approach makes things more maintainable IMO. Feel free to write code more concisely if the lack of concision offends. :slight_smile:

New we can use this code:

$MyString = fColorspaceLookup("Device RGB colorspace 1 0.5 0 1");

TaDa, again!:

or more realistically using $HighlightColor:

$MyString = fColorspaceLookup($HighlightColor);

So, which approach is better?

As we know there is no one right way! Use whichever appeals.

Here is your earlier file with my code added: (’_config’ note, new function, stamps, and four test notes. The test notes are pairs. The first feeds the target dictionary or function a string, the second uses a the value of $HighlightColor.

Here: TestingColorDictionary.-ed.tbx (629.2 KB)

I think that covers it :slight_smile:

2 Likes

Excellent. Many thanks MarkA. I like the TaDa’s!

Once you explain it, I now get it. Here is a very brief summary of your summary. Thank you for explaining both approaches:

  1. Using the /_config approach // in order to store and update the values with a note OR
  2. Using the function approach to make a call to the function to populate the values.

my thoughts …

I am planning to move forward with the function approach. Why?

  1. More modular and able to easier call and use in other tinderbox documents.
  2. Functions are new for me, this will be good practice.

BTW everyone…the RGB colorspace format is what SKIM uses to export the color of the highlight note rather than a color.

This might be useful if anyone uses SKIM. My pdf workflow starts with PDF Expert (I like its interface and annotations for both iOS and Mac, but for export I prefer Skim because i can customize the template: .md, tsv, csv and import directly.

Lastly, the other lesson learned here is how important it is to create a test document and work out your code before going live. In this example, I have renamed the attribute twice to customize its name to remind me of its use in Skim and added a description. Thanks MarkA, you have reminded us many times of this best practice.

This function will certainly come in handy for me…

Last question, in case i wanted to create an edict in a prototype to call the function
i assume i can call the function simply with

fColorspaceLookup($HighlightColor) in order to populate (this) note.

Thanks Mark
Tom

Good. I offered both to avoid an inevitable “why not use [some other method]” follow up. Both work. Putting my personal ‘hat’ on , I think the function route is easier to maintain (the individual key:value; pairs are easily seen edited/amended. Plus the library can easily be moved to/shared with other documents or users. The function itself required no attribute for storage as the dictionary data is in the function code an assembled as needed: @eastgate might have a view as to whether that is best practice. I assume for a few terms it’s moot. If the dictionary was 100 terms, then building it each time the function is run (if indeed the function runs often) it might be a different case.

Almost, but you will need to pass the function’s return value into a local attribute to make use of it, for instance putting it in $MyColor:

$MyColor = fColorspaceLookup($HighlightColor)

QQ: I noticed

“iDevice is a string input with a dictionary key value”,

Is ‘iDevice’ as specific input variable term or is can it be any name I choose? It would be my assumption it could be any variable string name, such as "iMyInput’ but would need to be replaced, in both places

at the top
function fColorspaceLookup(iDevice){ → function fColorspaceLookup(iMyTerm){

and at the bottom
return vColorDict[iDevice] → return vColorDict[iMyTerm]
}

Correct?
Thanks
Tom

It is specific in that it names the first (and here, only) function argument. Wherever that argument is referenced within the function, the same name must be used when referencing the argument from within the function. So, you ask:

Yes. You are changing the variable name used to define the argument, so the argument name and all references to it within the function must be the same name.

Essentially, by naming an argument you are also implicitly defining a variable of that that same name that must be used within the function if desiring to get the value of the argument, as passed in by the action code.

I’ve just written a significant addition to the aTbRef article on function arguments. I’d be interested to know if it helps explain things a bit more clearly. If not it would be extremely useful to know at what point people lose track of the subject being explained.

†. Note, my expectation the article is read in full and as part of the overall section in Functions. It is simply too complex to try an answer each possible narrow question (and the resource is a reference not a tutorial).

1 Like

I will begin reading it in full today and give you some feedback. On behalf of the Tinderbox community, we are very grateful to have your kindness, generosity and work.

“it would be extremely useful to know at what point people lose track of the subject being explained.”

funny, I feel I am the poster child of people running off the tracks. :slight_smile:
Tom

1 Like

Far from it, it happens to us all.