How can I loop through the results of an AppleScript to find the variables that have a boolean value of 1?

I'm using Applescript with Pashua: Native macOS dialogs for scripting languages. I'm using checkboxes in the dialog box, and I can get the output of those as a result in the script editor, i.e., when cat and cat 2 are checked, I get:

{cat:"1", cat4:"0", cat2:"1", cat3:"0"}

But what I need to do is loop through the checkboxes to find only those that have been toggled to 1, and I don't know where to start.

How can I loop through all categories - cat, cat2, cat3, cat4, etc. - in the result, find only those that are boolean 1, and then output those in one variable, separated by a comma.

I.e. using this script result

{cat:"1", cat4:"0", cat2:"1", cat3:"0"}

how can I loop through and get a variable that has a value of:

cat1, cat2


This is the script that generates the dialog box and the checkboxes:

tell application "Finder" to set thisFolder to (container of (path to me)) as text -- get the folder path
try
    set thePath to alias (thisFolder & "Pashua.scpt")
    set pashuaBinding to load script thePath

    tell pashuaBinding
        try
            set dialogConfiguration to my getDialogConfiguration() -- configure the dialog
            set dialogResult to showDialog(dialogConfiguration, "") -- show the dialog

        end try
    end tell
end try

on getDialogConfiguration() -- return the configuration string
    return "

# Add category checkboxes
txtcats.type = text
txtcats.default = Categories
cat.rely = -18
cat.type = checkbox
cat.label = Category 1
cat2.type = checkbox
cat2.label = Category 2
cat3.type = checkbox
cat3.label = Category 3
cat4.type = checkbox
cat4.label = Category 4

"
end getDialogConfiguration

AppleScript records are a poorly implemented construct, appearing to emulate what is referred to in some languages as an associative array, but doing a half-arsed job of it.

What are referred to as properties in a record, i.e. cat, cat4, etc. in your case, aren't things that can be referenced indirectly, therefore it isn't possible to read them as values and store them in a variable through which you could access the record item associated with that property.

In other words, one cannot do any of these:

set R to {cat:"1", cat4:"0", cat2:"1", cat3:"0"}

set item_name to cat  # Error: the variable cat is not defined
return item_name of R

set item_name to "cat"
return item_name of R # Error: can't get item_name of {cat:"1", ...}

set item_name to a reference to cat
return item_name of R # [ As above ]

You can, of course, do this:

set item_value to cat of R

but that requires you already hold an awareness of the property name "cat".


The simplest way to get around this problem is to cast the AppleScript record into a different data type of another language that gives you full access to the associative relationship between the paired entries.

Your two options are Objective-C , and JavaScript:

AppleScript-ObjC

AppleScript records bridge to what Objective-C and many other languages refer to as dictionaries, which are—for all intents and purposes to us—the same as associative arrays (they differ under the hood in how data is stored and accessed, but this makes little difference to us).

We need to transform the AppleScript record into an Objective-C NSDictionary class object, then we can search through its keys (what was referred to above as properties) and values indiscriminately:

use framework "Foundation"

property this : a reference to the current application
property NSDictionary : a reference to NSDictionary of this


set R to {cat:"1", cat4:"0", cat2:"1", cat3:"0"} # Swap in the return value of your script

set D to NSDictionary's dictionaryWithDictionary:R
return (D's allKeysForObject:"1") as list 
    --> {"cat", "cat2"}

If you want to stick this in a function to use to search for some arbitrary value in some arbitrary record, then:

on keys from R as record given data:V : missing value
    local R, V

    script
        use framework "Foundation"
        property this : a reference to current application
        property nil : a reference to missing value
        property dict : a reference to NSDictionary of this

        property object : R
        property value : V

        on fn()
            tell (dict's dictionaryWithDictionary:object)
                if value = nil then return ¬
                    allKeys() as list
                allKeysForObject_(value) as list
            end tell
        end fn
    end script

    result's fn()
end keys

Then:

return the keys from {cat:"1", cat4:"0", cat2:"1", cat3:"0"}

will return {"cat", "cat4", "cat2", "cat3" }, i.e. all the keys, and

return the keys from {cat:"1", cat4:"0", cat2:"1", cat3:"0"} given data:"0"

will return only the ones who are associated with the value "0".