Dictionary Operations

Operations involving dictionaries and other variables:

The result of any operation that uses a dictionary as one of the operands and a non-dictionary as the other will always take the root value of the dictionary as the value to be used for the operation. Note however, it is extremely uncommon to assign a root value to a dictionary.

Accessing values in a dictionary:

Values within a dictionary can be accessed using an array-like syntax.

Examples:

X = Dictionary();
X["A"] = 42;
Y = X["A"];   { Y now holds the value 42 }

Retrieving an array of the keys from a dictionary:

The function ListKeys will (by default) return a one-dimensional array of the keys stored in a dictionary

Rval = ListKeys ( dictionary );

Example:

X =  Dictionary();
X["A"] = 15;
X["B"] = 24;
Rval = ListKeys(X);

Rval will now contain a two-element array, containing the values "A" and "B".

Iterate through the elements of a dictionary

The function GetNextKey will return each successive key within a dictionary. If you don't know the first key, then a call to GetNextKey without a key to start from, will return the first key in the dictionary. But, given that the keys in a dictionary are not enumerated like elements in an array, which is the first and how is the order defined? GetNextKey allows you to specify that using an Order parameter, which may be alphabetic or ordinal (by when the key was added), either forward or backward.

Result_str = "";
MyDict = Dictionary();
MyDict["key4"] = "contents4";
MyDict["key1"] = "contents1";
MyDict["key3"] = "contents3";
MyDict["key2"] = "contents2";
 
CurVal = GetNextKey(MyDict, Invalid, 0, CurKey);
WhileLoop(Valid(CurKey),
  Result_str = Concat(Result_str, " """, CurVal, """");
  CurVal = GetNextKey(MyDict, CurKey, 0, CurKey);
);

Construct an array using a dictionary

If building an array from an external data source, you may not know how many elements there are and therefore will not know how much space to allocate for your array. A solution is to store the incoming elements to a dictionary, then transfer them to an array upon completion. (Or, leave them in the dictionary if that is more convenient for later operations.)

For each element you add to the dictionary, assign a key that is an incrementing number, starting with 0. You can then use ListKeys(Dict, 1, 2) to transfer the values to an array.

Retrieving the root value from a dictionary:

The root value of a dictionary can be obtained by either of two methods:

Directly:

Y =  X[""];    { where X is a dictionary }

Via a function:

Y =  RootValue( X );

In general, the result will be identical, except for the case where the root value is another dictionary. In such a case, RootValue will traverse the dictionaries until it finds the first root value that is not another dictionary.

In the case where all the root values are other dictionaries (a circle) then RootValue will return a dictionary, selecting the first root value after the one indicated in the command that points to an earlier value.

Advanced Situation - Dictionaries containing dictionaries:

Given three nested dictionaries where:

  • The root of dictionary X is dictionary Y
  • The root of dictionary Y is dictionary Z
  • The root of Z is the integer 42.

If you retrieve the root of x directly:

RVAL =  X[""];

Then, RVAL is now dictionary Y.

If you were to use the RootValue() function instead:

RVAL = RootValue(X);

RVAL is now the integer 42

Assignment operations involving dictionaries

When assigning a dictionary to a variable using the assignment operator (=) , the result is a pass-by-reference, effectively creating an alias for the dictionary rather than a copy.

Example:

X = Dictionary(); { create an empty dictionary }
Y = X;            { assign it to Y }
X["A"] = 42;      { create a node in X with key "A" & value 42 }
Y["A"] == 42;     {  TRUE because Y is an alias for X }

A function exists to do a pass by value, allowing you to create a copy of a dictionary:

RVAL = DictionaryCopy( dictionary,  [deep],  [acyclic],  [lock]);

The three optional parameters, deep, acyclic and lock are each Boolean values with a default of FALSE.

  • Deep       If true, all contained dictionaries are copied as well as the dictionary referred to by name. Note that if Deep is set to FALSE, the copied dictionary will not be missing the contained dictionaries - the difference is that in one case, the contained dictionaries are copied as well as the base dictionary, and in the other, the copy of the base dictionary will also include the original, contained dictionaries.
  • Acyclic  If true, cyclic links are removed
  • Lock         If true, all values in the copy will be locked as constants.

Adding and Removing Keys

Keys and values can be added to a dictionary by simply referencing them like so:

X = Dictionary(); {  creates a new, empty dictionary }
X["A"] = 42;   { adds a new key-value pair to dictionary X }

Keys and their associated values can be removed from a dictionary using the DictionaryRemove() function as follows:

DictionaryRemove(dictionary, key);

The given key, specified in the second parameter, and its associated data will be removed from the given dictionary specified in parameter 1.

Testing whether an object is a dictionary

The ValueType() function will work as expected on a dictionary unless you have assigned a root value, which is rarely done. In the case where there is a root value, ValueType() will return the type of that root value.

The function HasMetaData() will determine whether a value has metadata, unless that value is a dictionary: 

Rval  =  HasMetaData(Val);