Class

Dictionary


Description

An object that contains a list of key-value pairs. Both keys and values are Variants. ASCII String keys are case-insensitive, but non-ASCII String keys can be case-sensitive. String keys are encoding-sensitive.

Properties

Name

Type

Read-Only

Shared

BinCount

Integer

KeyCount

Integer

Methods

Name

Parameters

Returns

Shared

Clone

Dictionary

Constructor

keyComparison As Dictionary.KeyComparisionDelegate

Constructor

ParamArray entries As Pair

HasKey

key As Variant

Boolean

Key

index As Integer

Variant

Keys

Variant()

Lookup

key As Variant, defaultValue As Variant

Variant

Remove

key As Variant

RemoveAll

Value

key As Variant

Variant

key As Variant, Assigns value As Variant

Values

Variant()

Delegate Methods

Name

Parameters

Returns

KeyComparisionDelegate

leftKey As Variant, rightKey As Variant

Integer

Property descriptions


Dictionary.BinCount

BinCount As Integer

The number of bins the hash table uses. This is a measure of the hash table size, independent of the number of items the Dictionary contains.

Normally, you do not need to be concerned with bins and the hash table. BinCount would be of use to you only if you have very large dictionaries consisting of thousands of entries and you want to try to optimize performance.

If you set BinCount to a positive value, the Dictionary will use that number of bins regardless of the number of items in the Dictionary.

If you set BinCount to a value equal to or less than zero, the Dictionary will pick whatever value it thinks is appropriate for the number of items in the Dictionary. It will dynamically change the number of bins as items are added or removed from the Dictionary (or until you assign a positive value to BinCount).

The latter is the default behaviour.

This example sets the number of bins:

Var d As New Dictionary
d.BinCount = 100

Dictionary.KeyCount

KeyCount As Integer

The number of key-value pairs in the Dictionary.

This property is read-only.

Returns the actual Count, not the Ubound of an array.

The following code displays the number of key-value pairs:

Var d As New Dictionary
// display the entries for the dictionary
MessageBox(d.KeyCount.ToString)

Method descriptions


Dictionary.Clone

Clone As Dictionary

Performs a shallow clone of the Dictionary, resulting in a new Dictionary that can be manipulated independently of the first. A shallow clone means that if a Dictionary Value or Key refers to a class instance, its contents are not also cloned.

Clone a Dictionary and then change the original:

Var d1 As New Dictionary
d1.Value("Test") = "Hello, World!"

Var d2 As Dictionary
d2 = d1.Clone

d1.Value("Test") = "Changed!"

// d2.Value("Test") is still "Hello, World!"

Dictionary.Constructor

Constructor(keyComparison As Dictionary.KeyComparisionDelegate)

Note

Constructors are special methods called when you create an object with the New keyword and pass in the parameters above.


Dictionary.Constructor

Constructor(ParamArray entries As Pair)

Note

Constructors are special methods called when you create an object with the New keyword and pass in the parameters above.

The parameter is the list of Pairs that will make up the Dictionary.

This example passes the specs for a rectangle as as a list of Pairs. The key*s are Top, Left, Width, and Height and the values are the values that belong to each *key value.

Var d As New Dictionary("left" : 0, "top" : 10, "width" : 300, "height" : 300)

Dictionary.HasKey

HasKey(key As Variant) As Boolean

Returns True if key is in the Dictionary and False if it is not.

Returns a Boolean. The HasKey function is encoding-sensitive. The Dictionary works off hash functions and the hash of a UTF-16 string is vastly different from the hash of a UTF-8 string.

This example checks to see if the key corresponding to the passed color is in the Dictionary.

If d.HasKey(Color.Red) Then
  MessageBox(d.Value(Color.Red))
Else
  MessageBox("The Red Key is not in the dictionary.")
End If

Dictionary.Key

Key(index As Integer) As Variant

Returns the value of key for the item in the Dictionary at the index passed.

Keys are not case-sensitive, but they are encoding-sensitive. If there is no item in the Dictionary at the index passed, a call generates an OutOfBoundsException error.

Var d As New Dictionary
d.Value(Color.Red) = "This is pure red."
d.Value(Color.Blue) = "This is pure blue."
MessageBox(d.Value(d.Key(1))( // retrieves "This is pure blue."

Dictionary.Keys

Keys As Variant()

Returns all the keys in the Dictionary as an array of Variants.

The order is stable and matches the order returned by the Values method at least until the Dictionary is modified. Use this method with For Each or For...Next to loop through all the keys. Keys are not case-sensitive, but they are encoding-sensitive.

Suppose you have a Dictionary wordCounts whose keys are words, and whose values are the number of occurrences of the key in some text. You can produce a list of words sorted by count as follows.

Var word() As String
Var count() As Integer

For Each key As Variant In wordCounts.Keys
  word.Add(key)
  count.Add(wordCounts.Value(key))
Next
count.SortWith(word)

Dictionary.Lookup

Lookup(key As Variant, defaultValue As Variant) As Variant

Looks up the passed value of Key. Returns a Variant.

If Key is found, it returns the corresponding value. If key is not found, it returns the passed defaultValue.

This example looks up the passed color in the Dictionary.

Var d As New Dictionary
d.Value(Color.Red) = "This is pure red."
d.Value(Color.Blue) = "This is pure blue."

Var a As Variant
a = d.Lookup(Color.Red, "Default color")

Dictionary.Remove

Remove(key As Variant)

Removes the key th value-key pair from the Dictionary.

If key is not in the Dictionary, it raises a KeyNotFoundException error.

The following code removes the passed entry from the Dictionary:

d.Remove(Color.Red)

Exception err As KeyNotFoundException
  MessageBox("You tried to access a nonexistent item!")

Dictionary.RemoveAll

RemoveAll

Removes all entries from the Dictionary. This invalidates all iterators that were created from the Dictionary.

Remove all entries from a Dictionary:

d1.RemoveAll

Dictionary.Value

Value value As Variant

Retrieves a value to the key item in the Dictionary.

Value(value As Variant, Assigns value As Variant)

Assigns a value to the key item in the Dictionary.

The Value function is encoding-sensitive. The Dictionary works of hash functions and the hash of a UTF-16 string is vastly different than the hash of a UTF-8 string.

If you attempt to read a value for a key that is not in the Dictionary, a KeyNotFoundException error is raised. To avoid the exception, use the Lookup method to provide a default value if the key is not found or use the HasKey method to check if the key exists.

The Dictionary example in the Examples folder allows you to enter and display Dictionary entries. It uses only strings for the key and value, but you can actually use any type that can be stored as a Variant. The fields KeyField and ValueField contain the new key:value pair.

To use the example, enter a key and value pair and then press the “Set Value for Key” button. Its code is:

// add a value the same way you would set the value
// the key is a variant, which means it can be
// any data type.
//
// the value is also a variant
// however, this example only uses strings for keys and values

myDictionary.Value(KeyField.Text) = ValueField.Text

UpdateListbox

UpdateListbox is a window method and it repopulates the ListBox.

ListBox1.RemoveAllRows

For Each entry As DictionaryEntry In MyDictionary
  ListBox1.AddRow(entry.Key)
Next

Dictionary.Values

Values As Variant()

Returns all the values in the Dictionary as an array of Variants.

The order is stable and matches the order returned by Keys at least until the Dictionary is modified. Use this method with For Each to loop through all the values.

The following code retrieves the entries in the Dictionary and populates an array of Variants:

Var d As New Dictionary
d.Value(1) = "123"
d.Value(2) = "234"
d.Value(3) = "123"

Var v() As Variant
v = d.Values // after this line v will be an array of variants that are all the values in the dictionary

Delegate descriptions


Dictionary.KeyComparisionDelegate

KeyComparisionDelegate(leftKey As Variant, rightKey As Variant) As Integer

Implement this delegate if you would like the Dictionary to support case-sensitive keys. Return integer with value like String.Compare function.

Notes

The Dictionary class provides the functionality of the Collection class and offers several advantages: With the Collection class, the time taken to locate an item is a function of the number of items in the Collection because the search is sequential. A Dictionary uses a hash table, making the time (relatively) independent of the number of items. It is designed for high-speed lookups. Also, the key parameter in a Dictionary is a Variant, but is a String in the Collection class, giving you greater flexibility. On the other hand, the Collection can store multiple values per key. When you assign a value to a key that is already in the Dictionary, the new value replaces the old one

The Pair class also stores key-value items. The Pair class stores the key-value items in its Left and Right properties and an array of pairs can be set up as a linked list. The Pair class has only the two properties that contain the values of the pair.


Iterating through a Dictionary

To iterate through the contents of a Dictionary, use the DictionaryEntry class.

String key differences

Dictionaries use hashes for their lookup functions. Because of this, string keys need to match exactly; otherwise the Dictionary will not consider them equal. The only exception to this rule is with regard to string case. The characters "a" and "A" are treated as identical in Dictionary keys because of a case-insensitive hashing function. However, non-ASCII characters such as "é" and "É" are not treated as identical in Dictionary keys, even though they are equal in a direct string comparison.

While a UTF-16 string can be compared to a UTF-8 function in your code, they will provide different hashes when working with dictionaries.

Although the keys are case-insensitive, the case of the key is remembered. And the case of the key is not changed if a subsequent assignment uses a different case for the key. For example:

Var d As New Dictionary
d.Value("a") = "lower"
d.Value("A") = "UPPER"

MessageBox(d.Value("a")) // Displays "UPPER"
MessageBox(d.Value("A")) // Displays "UPPER"

// The actual key value is "a" as you can test using the Key method:
MessageBox(d.Key(0)) // Displays "a"

Integer key differences

Due to a particularity of Variant comparison, it is possible that Integer keys of different types may not evaluate as equivalent. For example,

Var v1 As Int32 = -1
Var v2 As Int64 = -1

Var d As New Dictionary
d.Value(v1) = "something"
If d.HasKey(v2)  Then
  // Won't get here, because the two keys are not considered equivalent
End If

Case-Sensitive keys

While Dictionary keys are case-insensitive, you can create case-sensitive keys if you need them:

This function provides a case-sensitive comparision:

Public Function CaseSensitiveKeyComparisionDelegate(leftKey As Variant, rightKey As Variant) As Integer
  Return leftKey.StringValue.Compare(rightKey.StringValue, ComparisonOptions.CaseSensitive)
End Function

You then call the function above when creating a Dictionary:

Var d As New Dictionary(AddressOf CaseSensitiveKeyComparisionDelegate)

d.Value("Hello") = 123
d.Value("hello") = 234

Break // The dictionary has now 2 entries in the dictionary

Sample code

The following code takes advantage of the fact that the key is a Variant, and not necessarily a number. In this example, the keys are colors and the values are descriptions.

Var d As New Dictionary
d.Value(Color.Red) = "This is pure red."
d.Value(Color.Blue) = "This is pure blue."
MessageBox(d.Value(d.Key(1))) // displays "This is pure blue."
Exception err As RuntimeException
  If err IsA KeyNotFoundException Then
    MessageBox("Key not in the dictionary")
  End If
  If err IsA OutOfBoundsException Then
    MessageBox("The index of the key is out of bounds!")
  End If

If the index passed to the Key method in the line:

MessageBox(d.Value(d.Key(1)))

is not an element in the Dictionary, an OutOfBoundsException occurs and the Exception block at the end of the method will trap it. You could also retrieve this value in the Dictionary by passing the Value method the key rather than the key's index

MessageBox(d.Value(Color.Blue))

In this case, if you pass a key that is not in the Dictionary, a KeyNotFoundException will occur and the Exception block will also trap it and display the appropriate error message.

This code returns the value of KeyCount for the above code:

Var d As New Dictionary
d.Value(Color.Red) = "This is pure red."
d.Value(Color.Blue) = "This is pure blue."
MessageBox(d.KeyCount.ToString) // displays "2"

Instead of the Exception block, you could first use the HasKey method before trying to access the value:

If d.HasKey(Color.Red) Then
  MessageBox(d.Value(Color.Red))
Else
  MessageBox("Key not in the dictionary!")
End If

Compatibility

All project types on all supported operating systems.

See also

Object parent class; DictionaryEntry, KeyNotFoundException error; Collection, Pair, and Variant classes