How Do I Get the Size of a Dictionary

I have a dictionary with 3 key value pairs. How do I find out the size? in this 3?
I could increment a counter but it seems tacky.

Ben

Do you mean the total of the three Dictionary entries, assuming all three entires are numbers?

In which case a For Each Action can do it.

I suppose a For Each Action is a kind of counter but it's pretty concise. The two Green colored Actions are the ones that are doing the adding up of the values.

The single line of code to allow each Dictionary value to be added to the sum is:

LOCAL__Total + CALCULATE(%Dictionary[DCT__TempTest,%Variable%LOCAL__Key%]%)

Where DCT__TempTest is a placeholder for whatever your dictionary is called.

Don't worry about the red colored numbers - that's just because the code doesn't work until the Macro is run each time.

Oh, and because the For Each Action simply goes through all the keys of the dictionary (no more and no less) the coding in the green Actions will work no matter how many keys you have. I set 3 entries at the start, because your example was 3. But it could be 19, 100 or whatever number of keys the Dictionary has. In that way it is different to an incrementing counter.

EXAMPLE Add Total of Dictonary Entries.kmmacros (4.6 KB)
EXAMPLE Add Total of Dictonary Entries

Another way to do this is to simply create a key in the dictionary, let's call it "Quantity", which you initialize to zero and add one to it whenever you create a new dictionary key. It's more work and more error-prone, but if I needed such a count, I would certainly consider it. I guess it depends on how often you need to obtain this number and how often the dictionary changes.

In manual:Dictionaries [Keyboard Maestro Wiki] you will see see examples of reading dictionaries with osascript (AppleScript and JavaScript for Automation)

in AppleScript, given a KM Dictionary with the name "Avian", for example, you might write:

set dictName to "avian"

tell application "Keyboard Maestro Engine"
    length of ((dictionary keys of dictionary dictName) as list)
end tell

or in JavaScript for Automation:

Application("Keyboard Maestro Engine")
.dictionaries.byName("Avian")
.dictionaryKeys()
.length

1 Like

That is informative and insightful. However I don't see this info on the wiki on the page you cited. Could it be added?

Yep that can work for Dictionaries with a static name.

eg. Avian but mine are like Avian1, Avian2, Avian3 and I use an if "starts with contain" eg. Avian(n) to loop through the dictionary.
I could have done a regex to the number on the end eg. Avian3 but then what If I deleted a key value pair. Perhaps im doing it wrong.
Perhaps it should have been Dictionary as a fixed name and then Keys as a dynamic.
eg. Dictionary: Avian, Key: Code1, Code2, Code3 etc.

Anyways, how would I change that Execute Javascript for Automation to fit with my Avian1 and so on.

Ben

If we adapt the script a little, then:

  • you can then supply any dictionary name as a Keyboard Maestro variable
  • get a message if no dictionary with the given name is found
  • get a key count if a dictionary is found by that name

Number of keys in a named dictionary.kmmacros (2.2 KB)

Ohhh. when you said you wanted "the size of the dictionary" I thought you meant "the number of entires."

Some days I misinterpret the question. Sorry.

Even so, if you manually keep track of the size as you add and delete entries, and store that value in one of the dictionary's keys, that would work and would be the fastest solution. I wouldn't hesitate to do that.

How do I respond back to this post with a macro and its snapshot?

Sorry that there seems to be a lot of intervening noise :slight_smile:

You can include the name of the poster, e.g. @complexpoint

How can we help you with that sketch of a macro ? If you have a working macro of your own which you would like to share here, we could integrate the mapping of dictionary names to key counts.

Actions (v10.0.2)

Keyboard Maestro Actions.kmactions (13 KB)

So ive used your code but I have to loop through the dictionary twice. First time to get the size, Second time to know when to append or not append | to the end of the string so that It could be separated inside a combobox.

Is there a better way to make it more concise, Tacky with two for each loops

Could you give us a single sentence to summarise the context of your macro, and what you need it to do within that context ?


In the meanwhile, one more general approach is to:

  1. Create a single new JSON object for all dictionary names and their corresponding keys counts
  2. Save that as a KM variable
  3. Use Keyboard Maestro's %JSONValue% token as a way of extracting the key-counts that you want, whenever you want.

e.g. something like:

All dictionary sizes.kmmacros (2.4 KB)

1 Like

Incidentally a fractionally more efficient version of the script (more cacheing), would be:

Expand disclosure triangle to view JS Source
(() => {
    "use strict";

    const
        kme = Application("Keyboard Maestro Engine"),
        dictionaries = kme.dictionaries,
        byName = k => dictionaries.byName(k);

    return JSON.stringify(
        dictionaries.name().reduce(
            (a, k) => Object.assign(
                a, {
                    [k]: byName(k).dictionaryKeys.length
                }
            ), {}
        ), null, 2
    );
})();

the point of the macro is to build up multiple dictionaries or json objects and navigate them in input boxes to get where I needed to get to. eg. Accessing one dictionary value might point to another dictionary and the process repeats.

Ben

1 Like