Global Dictionaries

Panorama allows a programmer to set up multiple “global dictionaries”. These are similar to Data Dictionaries stored in global variables, but are much faster because these global dictionaries are not converted to/from binary data each time they are modified, they are simply kept full time in the internal dictionary format. So if you need to frequently access or modify a large dictionary (hundreds of items or more), a global dictionary can give you much improved performance. Note: If needed, you can use the getglobaldictionary( function to convert a global dictionary into a regular data dictionary, and use this statement to convert a regular data dictionary into a global dictionary.

A global dictionary is set up automatically whenever you use the setglobaldictionaryvalues statement to set a value in the dictionary. This example sets up a global dictionary with three values: Color, Scale and Size.

    setglobaldictionaryvalues "MyValues","Color","Violet","Scale",80,"Size","Large"

Later, you can use the globaldictionaryvalue( function to retrieve any of these values, for example the scale.

    globaldictionaryvalue("MyValues","Scale") ☞ 80

If you need to change the scale value, you can do so at any time with another setglobaldictionaryvalues statement, like this:

    setglobaldictionaryvalues "MyValues","Scale",45

This will change the scale value while leaving the color and size (and any other values) alone.

### Global Dictionaries vs. Regular Data Dictionaries

You may have noticed that global dictionaries are similar to regular Data Dictionaries, so why the extra complication? Normally there is no reason, you should just stick with ordinary Data Dictionaries, for example, the previous example could be set up like this:

    letglobal MyValues = initializedictionary("Color","Violet","Scale",80,"Size","Large")

and then access the contents of regular dictionary like this:

    getdictionaryvalue(MyValues,"Scale") ☞ 80

The reason you might want to choose to use a global dictionary in some situations is performance. Global dictionaries use a special internal data format that is very fast, but is not compatible with the data format used by regular Panorama variables. In our tests global dictionaries are at least twice as fast as regular dictionaries, and if an application is frequently modifying values, at least ten times as fast, and possibly even many times faster than that. So if you have a task that does a lot of access and/or modification of a dictionary, it is worth a bit of extra trouble to use a global dictionary instead of a regular dictionary in a variable. If needed, you may even want to convert a regular dictionary to a global dictionary (see below), perform the time intensive task, and then convert back to a regular data dictionary again at the end (with the getglobaldictionary( function).

### Converting Between Global Dictionaries and Regular Data Dictionaries

Use the setglobaldictionaryvalues statement to convert a regular data dictionary into a global dictionary. When used this way the first parameter is the global dictionary name (as normal), and the second parameter is the data dictionary you want to convert. For example, this code creates a data dictionary named temp, then converts that into a global dictionary named Order.

    let temp = jsonimport(||| {"Name" : "Jack", "Color" : "Blue", "Size" : 38} |||)
    setglobaldictionaryvalues "Order",temp

Later you could use the getglobaldictionary( function to convert this global dictionary back into a data dictionary, and then into JSON.

    let revisedOrder = getglobaldictionary("Order")
    let orderJson = jsonexport(revisedOrder)

You would also use the getglobaldictionary( function to convert the global dictionary into a permanent variable, so that it could be saved.

    letpermanent mostRecentOrder = getglobaldictionary("Order")

If you wanted to restore the global variable the next time the database opens, use this code in the `.Initialize` procedure:

    setglobaldictionaryvalues "Order",mostRecentOrder

### Deleting Global Dictonaries and Dictionary Values

Normally Panorama keeps a global dictionary until you quit Panorama. If you need to remove an entire global dictionary, use the deleteglobaldictionaryvalues statement.

    deleteglobaldictionaryvalues "Order"

You can also use this statement to delete an individual value from a dictionary, like this:

    deleteglobaldictionaryvalues "Order","Color"

Or, you can delete several values at once, simply list each one.

    deleteglobaldictionaryvalues "Order","Name","Color","Price"

Finally, you can clear a global dictionary (remove all of the values) without actually deleting the dictionary itself. This leaves an empty dictionary.

    clearglobaldictionaryvalues "Order"

### Listing the Contents of a Global Dictionary

To get a list of all the global dictionaries that currently exist, use the globaldictionarykeys( function. If this function is used with no parameters, it will list all of the dictionaries.

    globaldictionarykeys() ☞ list of all global dictionaries

If you supply one parameter, it will list all of the keys in the specified dictionary. Please note that the values may be listed in any order, you cannot control the order.

    commalist(globaldictionarykeys("Order"),cr()) ☞ Name, Color and Size

If you want to list the contents of a global dictionary, use the getglobaldictionary( function to convert it to a regular data dictionary, then use the dumpdictionary( function to list the contents, like this:

    dumpdictionary(getglobaldictionary("Order"))

This will list all of the keys and values in the Order dictionary.

### Name Scope and Conflicts

In spite of the similar nomenclature, global dictionaries have nothing to do with global variables. They are completely separate, and you can create both a global variable and a global dictionary with the same name.

    letglobal MyValue = "hello"
    setglobaldictionaryvalues "MyValue","Color","Blue"

If you run the code above, you will now have two separate independent entities, a global variable named MyValue, and a separate global dictionary also named MyValue. This could be very confusing, so we recommend that you avoid using the same name for a global variable and a global dictionary, but Panorama will not stop you from doing this.

Since global dictionaries are global, they are shared among all databases. This means you need to take care that different databases and procedures don’t accidentally use the same name. The examples on this page used short names like MyValue and Order, but you want to avoid short names like that, and use long names that will avoid conflict, like OrderEntryPriceInfo.

### Building a Global Dictionary from a Database

The globaldictionarybuild statement builds a global dictionary by scanning an open database. It’s similar to the arraybuild statement, but builds a global dictionary instead of an array.

The primary purpose of this statement is that once the global dictionary is built, you can look up values in it with the globaldictionaryvalue( function. Because global dictionaries use a structure that is very efficient for searching, lookups performed this way can be hundreds of times faster than looking up directly from the database with the lookup( function. However, this speed increase is only practical if you plan to do many lookups without ever modifying the data. If you just plan to do a single lookup, or if the data is modified frequently (every time the data is modified you would have to use the globaldictionarybuild statement again), just using a regular lookup( statement is better.

For example, suppose you have a database named Contacts that contains names and email addresses. You can build a global dictionary with this information with a single line of code:

    globaldictionarybuild "ContactEmails","Contacts",Name,Email

Now suppose you have another database that also contains names and email addresses, and you wish to update the email addresses with the email addresses from the Contacts database. This database has fields named FullName and E-mail. This code will fill the E-mail field with the latest email addresses gleaned from the Contacts database.

    field "E-mail"
    formulafill catcherror(«E-mail»,globaldictionaryvalue("ContactEmails",FullName))

We tested this code on two databases with 20,000 records of data, the entire process (first building the global dictionary and then doing the formula fill) took about 3 seconds. We then tried this same operation using the lookup( function, like this:

    field "E-mail"
    formulafill lookup("Contacts",Name,FullName,Email,«E-mail»)

With the same 20,000 record databases, this operation took almost 7 minutes! Using globaldictionarybuild was 134 times faster. In our tests, the speed difference was larger as the databases got larger.

If you are considering using globaldictionarybuild with formulafill, however, you should probably take a close look at the join statement. Using the join statement, you can update the email addresses with a single line of code.

    join "Database","Contacts","Key","Name","SourceKey","FullName","«E-mail»",{Email}

The join statement uses the same high performance internal structure used by global dictionaries, so the perfomance is also very fast – about 3 seconds for our 20,000 record test databases.

See Also

- appenddictionaryvalue -- appends a value to an item in a dictionary (see Data Dictionaries).
- changedictionaryname -- changes the name (key) of an item in a dictionary (see Data Dictionaries).
- changedictionaryvalues( -- changes one or more values in a dictionary (see Data Dictionaries).
- classicdictionaryvalue( -- returns the value of an item in the dictionary, given its key (see Data Dictionaries). Unlike getdictionaryvalue(, this function does not treat keys as case sensitive.
- clearglobaldictionaryvalues -- clears (removes) all the keys and values from the specified global dictionary.
- copypartialdictionary -- builds a new dictionary and initializes it with values from an existing dictionary (see Data Dictionaries).
- copypartialdictionary( -- partially copies a dictionary (see Data Dictionaries).
- Data Dictionaries -- Overview of Panorama's key/value data dictionaries.
- deletedictionaryvalue -- deletes a key/value pair from a dictionary (see Data Dictionaries).
- deletedictionaryvalue( -- deletes one or more key/value pairs from a dictionary (see Data Dictionaries).
- deleteglobaldictionaryvalues -- deletes one or more global dictionary values.
- dictionaryassignmentscode( -- returns code that can be used to take the values in a dictionary (see Data Dictionaries) and assign them to fields or variables based on the dictionary keys.
- dictionarydifference -- builds an array that lists keys of dictionary values that are different between two dictionaries (see Data Dictionaries).
- dictionaryfromarray( -- builds a new dictionary and initializes it from a two dimensional text array (see Data Dictionaries and Text Arrays).
- dictionaryfromvariables( -- builds a new dictionary and initializes it from a list of variables (carriage return delimited).
- dictionaryvalueexists -- returns true or false depending on whether or not a key/value pair exists in a dictionary (see Data Dictionaries).
- dictionaryvalueexists( -- returns true or false depending on whether or not a key/value pair exists in a dictionary (see Data Dictionaries).
- dumpdictionary -- returns a carriage return separated array of dictionary keys and values (see Data Dictionaries).
- dumpdictionary( -- returns a carriage return separated array of dictionary keys and values (see Data Dictionaries).
- dumpdictionaryquoted -- returns a carriage return separated array of dictionary keys and values (see Data Dictionaries).
- dumpdictionaryquoted( -- returns a carriage return separated array of dictionary keys and values (see Data Dictionaries). The text values are quoted.
- dumpdictionarysource( -- returns a carriage return separated array of dictionary keys and values (see Data Dictionaries). The keys and values are quoted so that they could be used to re-assemble the dictionary with the initializedictionary( function.
- getdictionarykey -- returns the key of an item in the dictionary, given its value. This is essentially the opposite of the getdictionaryvalue( function (see Data Dictionaries).
- getdictionarykey( -- returns the key of an item in the dictionary, given its value). This is essentially the opposite of the getdictionaryvalue( function (see Data Dictionaries).
- getdictionaryvalue -- returns the value of an item in the dictionary, given its key (see Data Dictionaries).
- getdictionaryvalue( -- returns the value of an item in the dictionary, given its key (see Data Dictionaries).
- getglobaldictionary( -- converts a global dictionary into a regular dictionary.
- getstructurevalue( -- extracts a value from a structure of nested Data Dictionaries and/or Data Arrays.
- globaldictionarybuild -- builds a global dictionary by scanning a database.
- globaldictionarykeys( -- returns a cr()-separated array containing the keys in a global dictionary, or the names of all global dictionaries.
- globaldictionaryvalue( -- returns the value of an item in a global dictionary, given its key (see Global Dictionaries).
- info("timerinfo") -- returns a dictionary that contains all of the properties of the currently running timer.
- initializedictionary -- builds a new dictionary and initializes it with one or more key/value entries (see Data Dictionaries).
- initializedictionary( -- builds a new dictionary and initializes it with zero or more key/value entries (see Data Dictionaries).
- initializedictionaryvalue( -- builds a new dictionary and initializes it with one or more entries (see Data Dictionaries). This function is deprecated, we recommend using the initializedictionary( function instead.
- listdictionarykeys( -- returns a list of the keys in a dictionary collection.
- listdictionarynames -- returns a list of the names (keys) in a dictionary (see Data Dictionaries).
- mergedictionaries -- merges the contents of two or more dictionaries (see Data Dictionaries).
- mergedictionaries( -- merges the contents of two or more dictionaries (see Data Dictionaries).
- renamedictionarykey( -- changes the key (name) of one or more values in a dictionary (see Data Dictionaries).
- setdictionaryvalue -- changes a value in a dictionary (see Data Dictionaries).
- setglobaldictionaryvalues -- sets one or more key/value pairs in a global dictionary.
- setlocalsfromdictionary -- converts a dictionary into a collection of local variables. The names and values of the local variables will be derived from the dictionary contents.
- soundinfo( -- returns a dictionary that contains all of the properties of a sound.
- timerinfo( -- returns a dictionary that contains all of the properties of a timer.

History

Version | Status | Notes
10.2 | New | New in this version.