Provides a hash table, which maps string keys to values.
Dim ht As Hash Type
ht | : varname |
Type | : simple type |
A Hash is a one dimensioned 'array' and its index is a string. A Hash table has no size, just a number of elements. For Example, with Dim ht As Hash Int declares a dynamic table (array) ht of type Int, which has initially no elements.
Type specifies the data type of the values to be stored in the hash table. Type may be Byte, Boolean, Card, Short, Word, Integer, Long, Large, Currency, Single, Double, Date, String (variable-length strings only) and Variant.
A hash table supports the creation, storage, and retrieval of key/value pairs in memory. The hash table maps string keys to values; the index for hash tables is a case-insensitive string. When the type of the hash table is String, the hash table acts as a dictionary (string/string pair).
After declaring a hash, you can add elements of appropriate type to it, in one of two ways:
Hash Add ht["key"], value
ht["key"] = value
A Hash uses brackets to access an element. To access an element stored in a hash table, you simply specify the key.
value = ht["key"]
To obtain the number of elements of the hash table you use % as the key:
number_of_elements = ht[ % ]
To inquire if an element exists in the table prefix the key with a question mark:
If Not ht[? "key"] Then Hash Add ht["key"], value
A key cannot be duplicated, is case-insensitive and all keys must be unique. When you add a value with an already existing key, the value isn't added and an error is generated.
If you wish to use case-sensitive keys, this is possible by using a basic String to Hex conversion function as shown below:
Trace StrToHex("Hello")
Trace StrToHex("HELLO")
Debug.Show
Function StrToHex(s As String) As String
// Acknowledgements to (X) on GB32 Forum
Dim h As String, i
h = ""
For i = 1 To Len(s)
h = h & Hex(Asc(Mid(s, i, 1)))
Next i
StrToHex = h
End Function
Internally, the Hash is implemented as a double linked list. Each element has its own position (index) in the list. Therefore, a hash table can be accessed as if it were an array using a number as the index starting at 1. To mark a key as numeric value, rather than a string, precede the numeric value with %.
value = ht[% 1]
In the same way you can iterate over a hash table using For Next:
For i = 1 To ht[ % ]
Print ht[ % i]
Next
Another way to iterate over a hash table is by using For Each element In hashvar.
Dim e As Int // same type as Hash <type>
For Each e In ht[]
Print "Element = "; e; " at position "; Each; " and Key = "; ht[$ Each]
Next
The variable e receives the value from that position and must be of the same type as the type of the Hash. Each returns the current position (index) in the hash table.
A hash table can also store values without a key. The Hash is reduced to a double linked list, what it basically is. The only way to add key-less elements to the list is by using Hash Add. An advantage of Hash Add is that it gives control on the position of the elements.
Hash Add ht[], value
Hash Add ht[] Before idx, value
Hash Add ht[] After idx, value
To iterate over the list you can use For Next or For Each. The list variant of the hash table is used in quite some GFA-BASIC 32 commands like Split, Join, Eval, reSub, reMatch.
To remove an element use Hash Remove ht[ "key" | % index]
A hash table can be sorted by its keys, saved, loaded, and erased. The following commands are available:
Hash Erase | Deletes the entire hash table. |
Hash Sort | Sort the hash table by its keys using the Mode Compare setting. |
Hash Write | Save a hash table as an ASCII file. |
Hash Input | Load a hash table from an ASCII file. |
Hash Save | Save a hash table in binary format. |
Hash Load | Load a hash table in binary format. |
Other operations on a hash table are performed using the subscription notation [ ].
Subscript | Meaning |
---|---|
[ % ] | returns the number of elements |
[ % i ] | accesses the element by index i (position) |
[ k$ ] | accesses the element by key k$ (string) |
[ $ i ] | returns the key for the given index i. |
[ ? k$ ] | returns a Boolean indicating whether the key k$ exists. |
[ ?% i ] | returns a Boolean indicating whether the index i exists. |
[ # k$ ] | returns the index for the key k$. |
[ $$ k$ ] | returns the correct key string (upper and lower) for key k$. |
Example 1
Dim a As Hash String, e As String
Hash Add a[], "a"
Hash Add a[], "b"
Hash Add a[], "c"
Hash Add a[], "d"
a[% a[%]] = "e" // replace last element
a[% 1] = "1" // replace first element
a[ "Key" ] = "f" // add element
Print a[$$ "key"] // prints Key
For Each e In a[] // iterate over table
Print "(Pos)" & Each, " (element) " & e
Next
Example 2
Dim ha As Hash Int
// The value 27 will be assigned to element 1 with the key "a" and the index 1
ha["a"] = 27
// The value 29 will be assigned to element 2 with the key "xyz" and the index 2
ha["xyz"] = 29
// Output of element with index number 1:
Trace ha[% 1] // Prints 27
// Output by using the key "a":
Trace ha["a"] // Prints 27
// Output of element with index number 2:
Trace ha[% 2] // Prints 29
// Output by using the key "xyz":
Trace ha["xyz"] // Prints 29
// To get the key for the second element:
Trace ha[$ 2] // Prints xyz
// The only way to add a value without using a key
Hash Add ha[], 100
// Call Proc dst to iterate through the Hash Table
dst(ha[])
// Check is key "a" exists:
Trace ha[? "a"] // Prints True
// Check the correct formatting of key "a":
Trace ha[$$ "A"] // Prints a
// Check to see if 3 is a valid index or not:
Trace ha[? % 3] // Prints True
// To get the index which corresponds to key "xyz"
Trace ha[# "xyz"] // Prints 2
// Request the number of elements in the Hash ha[]
Trace ha[%] // Prints 3
Debug.Show
Procedure dst(ByRef h As Hash Int)
// Remember h is read-only
Local i%, j%
For Each i% In h[]
Debug.Print i%, Each, h[$ Each]
Next
EndProc
A Hash is passed ByRef to subroutines. Unfortunately, the argument is a const variable, so that the Hash is read-only and can't be modified.
Although the initial documentation says that it is possible to create a Hash Table full of Objects, this does not seem to be the case as there seems to be no way to assign the objects to the table. If the code below is run, a Syntax Error is thrown.
Dim a As Hash Object
Dim b As Object
Hash Add a["key"], b
[Reported by James Gaite, 15/02/2017]In addition, although syntactically it is possible to add a Hash Table as a property of a User-defined Type, there is no means of accessing it and, as UDTs in GFABasic are static, there is no room for the Hash to expand to accept new values. [Reported by Garibaldi, 16/11/2016]
Hash Add, Hash Erase, Hash Input, Hash Load, Hash Remove, Hash Save, Hash Sort, Hash Write
{Created by Sjouke Hamstra; Last updated: 29/05/2023 by James Gaite}