From WikiChip
Difference between revisions of "mirc/hash tables"
< mirc

(Deleting Items: grammar)
Line 1: Line 1:
 
{{mirc title|Hash Tables}}
 
{{mirc title|Hash Tables}}
A '''hash table''' is an associative array with key-value pairing. That is, a value stored in the table is associated with a specific key. Logically speaking, a basic table would like something like this:
+
A '''hash table''' is an associative array with item-data pairing. That is, data stored in the table is associated with a specific item. Logically speaking, a basic table would like something like this:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Key !! Value
+
! Item !! Data
 
|-
 
|-
|Key1 || value1
+
|Item1 || Data1
 
|-
 
|-
|Key2 || value2
+
|Item2 || Data2
 
|-
 
|-
|Key3 || value3
+
|Item3 || Data3
 
|}
 
|}
  
Line 16: Line 16:
 
== General Details ==
 
== General Details ==
  
Hash tables, unlike INI files, are stored completely in memory and are never written to disk, making them much faster when it comes to storing and retrieving information. The performance gain is much more obvious with a large amount of keyval pairs.
+
Hash tables, unlike INI files, are stored completely in memory and are never written to disk (unless the /hsave command is used), making them much faster when it comes to storing and retrieving information. The performance gain is much more obvious with a large amount of item/data pairs.
  
 
'''Note:''' Because hash tables are only in memory, it must be saved to a file if mIRC has to exit for any reason. You can reload the table from a file at a later period.
 
'''Note:''' Because hash tables are only in memory, it must be saved to a file if mIRC has to exit for any reason. You can reload the table from a file at a later period.
Line 31: Line 31:
  
 
<math>
 
<math>
   \text{buckets} = \frac{\text{number of keys that will be used}}{0.78}
+
   \text{buckets} = \frac{\text{number of items that will be used}}{0.78}
 
</math>
 
</math>
  
For example: a table with 100 buckets is optimal for 78 items. For 1000 items, 1300 buckets is best.
+
For example: a table with 100 buckets is optimal for 78 items. For 1000 items, 1300 buckets is best. '''Note:''' The maximum valid number of buckets is 10000.
  
 
== Adding Items ==
 
== Adding Items ==
  
The /hadd command is used to add a keyval pair to the table. The syntax is:
+
The /hadd command is used to add an item/data pair to the table. The syntax is:
  
<syntaxhighlight lang="mirc">hadd <table_name> <key> <value>
+
<syntaxhighlight lang="mirc">hadd <table_name> <item> <data>
hadd -b <table_name> <key> <&bvar></syntaxhighlight>
+
hadd -b <table_name> <item> <&bvar>
 +
An item can be added to the table with null data:
 +
hadd <table_name> <item>
 +
</syntaxhighlight>
  
 
Let's consider a table of favorite colors:
 
Let's consider a table of favorite colors:
Line 58: Line 61:
 
{| class="wikitable"
 
{| class="wikitable"
 
|+ "Colors" Hash Table
 
|+ "Colors" Hash Table
! Key !! Value
+
! Item !! Data
 
|-
 
|-
 
|John || Blue
 
|John || Blue
Line 70: Line 73:
 
To delete pairs from the table, you need to use the /hdel command. Its syntax is:
 
To delete pairs from the table, you need to use the /hdel command. Its syntax is:
  
<syntaxhighlight lang="mirc">hdel <table_name> <key>
+
<syntaxhighlight lang="mirc">hdel <table_name> <item>
hdel -w <table_name> <wild_key>
+
hdel -w <table_name> <wild_item>
 
;hdel has a -s switch which is the same as /hmake's</syntaxhighlight>
 
;hdel has a -s switch which is the same as /hmake's</syntaxhighlight>
  
A wildcard pattern for the key can be specified to delete multiple keys at once. If we go back to our example:
+
A wildcard pattern for the item can be specified to delete multiple items at once. If we go back to our example:
  
 
<syntaxhighlight lang="mirc">/hdel colors Mary</syntaxhighlight>
 
<syntaxhighlight lang="mirc">/hdel colors Mary</syntaxhighlight>
Line 82: Line 85:
 
{| class="wikitable"
 
{| class="wikitable"
 
|+ "Colors" Hash Table
 
|+ "Colors" Hash Table
! Key !! Value
+
! Item !! Data
 
|-
 
|-
 
|John || Blue
 
|John || Blue
Line 90: Line 93:
  
 
== Value retrieval ==
 
== Value retrieval ==
To get a value associated with a given key we will use the $hget identifier which has the following syntax:
+
To get a data value associated with a given item we will use the $hget identifier which has the following syntax:
  
<syntaxhighlight lang="mirc">$hget(<table_name>, <key>)</syntaxhighlight>
+
<syntaxhighlight lang="mirc">$hget(<table_name>, <item>)</syntaxhighlight>
  
 
For example, if we were to check what is John's favorite color from our table; we will use the following piece of code:
 
For example, if we were to check what is John's favorite color from our table; we will use the following piece of code:
Line 112: Line 115:
  
 
<syntaxhighlight lang="mirc">/hsave <table_name> <filename>
 
<syntaxhighlight lang="mirc">/hsave <table_name> <filename>
; The -o switch will override existing file
+
; The -s switch displays debug information
; The -a switch will append to an existing file
+
; The -a switch will append to an existing file, instead of the default overwriting
 
; The -i switch will create an ini file
 
; The -i switch will create an ini file
; The -b switch will treat the file as a binary file,
+
; The -n switch saves the file containing only the data and not the item names.
; making it possible to save things like carriage returns
+
; The -u switch avoids skipping temporary items created with /hadd's -uN switch.
; and line feeds.</syntaxhighlight>
+
; The -b switch will treat the file as a binary file, making it possible to save things like carriage returns and line feeds.</syntaxhighlight>
  
 
If we wanted to save our little colors table to an INI file, we could use the following piece of code.:
 
If we wanted to save our little colors table to an INI file, we could use the following piece of code.:
Line 131: Line 134:
 
<syntaxhighlight lang="mirc">; NOTE: The table must exists. I.e. you must have called /hmake first
 
<syntaxhighlight lang="mirc">; NOTE: The table must exists. I.e. you must have called /hmake first
 
/hload <table_name> <filename>
 
/hload <table_name> <filename>
; The -i switch will create an ini file
+
; The -s switch displays debug information
; The -b switch will treat the file as a binary file,
+
; The -i switch will read from an ini file containing lines of item=data
;        making it possible to save things like carriage returns and line feeds.</syntaxhighlight>
+
; The -n switch interprets the file as if it were /hsave'ed with the -n switch to contain only data, assigning item names as sequential integers beginning with 1.
 +
; The -m[N] switch creates the hashtable if it does not already exist, optionally giving it N buckets different than the default 100 buckets.
 +
; The -b switch will treat the file as a binary file, making it possible to save things like carriage returns and line feeds.</syntaxhighlight>
  
 
To load the table we've just saved we would use the following code:
 
To load the table we've just saved we would use the following code:
Line 146: Line 151:
 
;hfree has a -s switch which is the same as /hmake's</syntaxhighlight>
 
;hfree has a -s switch which is the same as /hmake's</syntaxhighlight>
  
With the -w switch you can specify a wildcard pattern. All matching tables will be freed.
+
With the -w switch you can specify a wildcard pattern. All matching tables will be freed. If you already deleted a table and try to delete it again, "hfree tablename" halts your script. You must either use $hget(tablename) to verify the table's existence, or use -w without a wildcard. "hfree -w tablename_without_wildcards"
  
 
== Iterating Over a Hash Table ==
 
== Iterating Over a Hash Table ==
Line 153: Line 158:
 
<syntaxhighlight lang="mirc">; Total Number of items in the table:
 
<syntaxhighlight lang="mirc">; Total Number of items in the table:
 
$hget(<table_name>, 0).item
 
$hget(<table_name>, 0).item
; Get the Nth Key
+
; Get the Nth Item
 
$hget(<table_name>, <Nth>).item
 
$hget(<table_name>, <Nth>).item
; Get the value associated with the Nth key
+
; Get the value associated with the Nth Item
 
$hget(<table_name>, <Nth>).data</syntaxhighlight>
 
$hget(<table_name>, <Nth>).data</syntaxhighlight>
  
'''Note:''' Iterating over a hash table like this is an inefficient way to retrieve values and keys. It's best to get a value using its key.
+
'''Note:''' Iterating over a hash table like this is an inefficient way to retrieve values and items. It's best to get a value using its item name.
  
 
An example of looping over every value in our Colors table will look like this:
 
An example of looping over every value in our Colors table will look like this:
Line 167: Line 172:
 
   ; iterate over each item
 
   ; iterate over each item
 
   while ($hget(Colors, %i).item) {
 
   while ($hget(Colors, %i).item) {
     ; print the key/value pair
+
     ; print the item/value pair
 
     echo -a %i $+ ) $v1 => $hget(Colors, $v1)
 
     echo -a %i $+ ) $v1 => $hget(Colors, $v1)
 
     inc %i
 
     inc %i
Line 179: Line 184:
 
2) John => Blue</pre>
 
2) John => Blue</pre>
  
== Searching for a key and value pair ==
+
== Searching for a Item and value pair ==
 
The $hfind identifier can be used to search the table for a particular pair.
 
The $hfind identifier can be used to search the table for a particular pair.
  
<syntaxhighlight lang="mirc">; The Nth key that matches the wildcard pattern
+
<syntaxhighlight lang="mirc">; The Nth Item name that matches the wildcard pattern
 
$hfind(<table_name>, <pattern>, <Nth>, w)
 
$hfind(<table_name>, <pattern>, <Nth>, w)
; The Nth key that matches the RegExp pattern
+
; The Nth Item that matches the RegExp pattern
 
$hfind(<table_name>, <pattern>, <Nth>, r)
 
$hfind(<table_name>, <pattern>, <Nth>, r)
; The Nth key that wildcard matches the text
+
; The Nth Item that wildcard matches the text
 
$hfind(<table_name>, <text>, <Nth>, W)
 
$hfind(<table_name>, <text>, <Nth>, W)
; The Nth key that RegExp matches the text
+
; The Nth Item that RegExp matches the text
 
$hfind(<table_name>, <text>, <Nth>, R)
 
$hfind(<table_name>, <text>, <Nth>, R)
; $hfind(...).data will search the data instead of the key.</syntaxhighlight>
+
; $hfind(...).data will search the data instead of the item name.</syntaxhighlight>
  
If you specify 0 for Nth key, the total number of matches will be returned instead. An example from our Colors table would be:
+
If you specify 0 for Nth Item, the total number of matches will be returned instead. An example from our Colors table would be:
  
 
<syntaxhighlight lang="mirc">//echo -a $hfind(Colors, *ary*, 1, w)</syntaxhighlight>
 
<syntaxhighlight lang="mirc">//echo -a $hfind(Colors, *ary*, 1, w)</syntaxhighlight>
Line 198: Line 203:
 
Which will return "Gary".
 
Which will return "Gary".
  
[[Category:mIRC|hash tables]]
+
== See Also ==
 +
More detailed information can be found at the pages for each hashtable-related command and identifier.
 +
{{collist
 +
|count = 3
 +
|style = width: 60%; display: inherit;
 +
|
 +
* {{mIRC|/hmake}}
 +
* {{mIRC|/hfree}}
 +
* {{mIRC|/hload}}
 +
* {{mIRC|/hsave}}
 +
* {{mIRC|/hadd}}
 +
* {{mIRC|/hdel}}
 +
* {{mIRC|/hinc}}
 +
* {{mIRC|/hdec}}
 +
* {{mIRC|$hget}}
 +
* {{mIRC|$hfind}}
 +
}}

Revision as of 02:16, 13 June 2018

A hash table is an associative array with item-data pairing. That is, data stored in the table is associated with a specific item. Logically speaking, a basic table would like something like this:

Item Data
Item1 Data1
Item2 Data2
Item3 Data3

mIRC provides facilities for manipulating the table and the values in variety of ways.

General Details

Hash tables, unlike INI files, are stored completely in memory and are never written to disk (unless the /hsave command is used), making them much faster when it comes to storing and retrieving information. The performance gain is much more obvious with a large amount of item/data pairs.

Note: Because hash tables are only in memory, it must be saved to a file if mIRC has to exit for any reason. You can reload the table from a file at a later period.

Creating a table

A hash table must be created before you can work with it. This also applies to loading a hash table from a file. To create a table you need to use the /hmake command. The syntax is:

hmake <table_name>
hmake <table_name> <buckets>
;hmake also have an -s switch which prints debug info

If you don't specify the number of buckets, the default is used which is 100. Generally speaking the number of buckets should be decided based on the following equation:

Equation buckets equals StartFraction number of items that will be used Over 0.78 EndFraction

For example: a table with 100 buckets is optimal for 78 items. For 1000 items, 1300 buckets is best. Note: The maximum valid number of buckets is 10000.

Adding Items

The /hadd command is used to add an item/data pair to the table. The syntax is:

hadd <table_name> <item> <data>
hadd -b <table_name> <item> <&bvar>
An item can be added to the table with null data:
hadd <table_name> <item>

Let's consider a table of favorite colors:

/hadd -ms colors John Blue
/hadd -s colors Mary Green
/hadd -s colors Gary Orange

The code above will produce the following result:

* Made hash table 'colors' (100)
* Added item 'John' to hash table 'colors'
* Added item 'Mary' to hash table 'colors'
* Added item 'Gary' to hash table 'colors'
"Colors" Hash Table
Item Data
John Blue
Mary Green
Gary Orange

Deleting Items

To delete pairs from the table, you need to use the /hdel command. Its syntax is:

hdel <table_name> <item>
hdel -w <table_name> <wild_item>
;hdel has a -s switch which is the same as /hmake's

A wildcard pattern for the item can be specified to delete multiple items at once. If we go back to our example:

/hdel colors Mary

Will leave our table looking like this:

"Colors" Hash Table
Item Data
John Blue
Gary Orange

Value retrieval

To get a data value associated with a given item we will use the $hget identifier which has the following syntax:

$hget(<table_name>, <item>)

For example, if we were to check what is John's favorite color from our table; we will use the following piece of code:

//echo -a $hget(colors, John)
;Blue

The $hget identifier can also be used to check if a table exists using the following syntax:

$hget(<table_name>)
; returns $null if the table does not exist

Saving/Loading Hash Table to/from file

Because a hash table is stored exclusively in memory, it is important to save it to a file if one wishes to keep its content after a reboot or shut down. If a hash table is not stored in a file before mIRC closes, it will be gone for good.

mIRC offers the /hsave and /hload commands to handle the saving and loading of hash tables from your hard disk.

The syntax for the /hsave command is:

/hsave <table_name> <filename>
; The -s switch displays debug information
; The -a switch will append to an existing file, instead of the default overwriting
; The -i switch will create an ini file
; The -n switch saves the file containing only the data and not the item names.
; The -u switch avoids skipping temporary items created with /hadd's -uN switch.
; The -b switch will treat the file as a binary file, making it possible to save things like carriage returns and line feeds.

If we wanted to save our little colors table to an INI file, we could use the following piece of code.:

/hsave -i Colors colors.ini
;colors.ini will have:
;  [hashtable]
;  Gary=Orange
;  John=Blue

To load a hash table we use the following syntax:

; NOTE: The table must exists. I.e. you must have called /hmake first
/hload <table_name> <filename>
; The -s switch displays debug information
; The -i switch will read from an ini file containing lines of item=data
; The -n switch interprets the file as if it were /hsave'ed with the -n switch to contain only data, assigning item names as sequential integers beginning with 1.
; The -m[N] switch creates the hashtable if it does not already exist, optionally giving it N buckets different than the default 100 buckets.
; The -b switch will treat the file as a binary file, making it possible to save things like carriage returns and line feeds.

To load the table we've just saved we would use the following code:

/hload -i Colors colors.ini

Deleting a Table

To complete destroy a table and all its values, you can use the hfree command:

/hfree <table_name>
/hfree -w <*wild*table*>
;hfree has a -s switch which is the same as /hmake's

With the -w switch you can specify a wildcard pattern. All matching tables will be freed. If you already deleted a table and try to delete it again, "hfree tablename" halts your script. You must either use $hget(tablename) to verify the table's existence, or use -w without a wildcard. "hfree -w tablename_without_wildcards"

Iterating Over a Hash Table

The $hget identifier can be used to iterate over the hash table. The syntax is:

; Total Number of items in the table:
$hget(<table_name>, 0).item
; Get the Nth Item
$hget(<table_name>, <Nth>).item
; Get the value associated with the Nth Item
$hget(<table_name>, <Nth>).data

Note: Iterating over a hash table like this is an inefficient way to retrieve values and items. It's best to get a value using its item name.

An example of looping over every value in our Colors table will look like this:

Alias print_fav_colors {
  var %i = 1
  echo Colors Table:
  ; iterate over each item
  while ($hget(Colors, %i).item) {
    ; print the item/value pair
    echo -a %i $+ ) $v1 => $hget(Colors, $v1)
    inc %i
  }
}

The execution of the alias (/print_fav_colors) will produce the following result:

Colors Table:
1) Gary => Orange
2) John => Blue

Searching for a Item and value pair

The $hfind identifier can be used to search the table for a particular pair.

; The Nth Item name that matches the wildcard pattern
$hfind(<table_name>, <pattern>, <Nth>, w)
; The Nth Item that matches the RegExp pattern
$hfind(<table_name>, <pattern>, <Nth>, r)
; The Nth Item that wildcard matches the text
$hfind(<table_name>, <text>, <Nth>, W)
; The Nth Item that RegExp matches the text
$hfind(<table_name>, <text>, <Nth>, R)
; $hfind(...).data will search the data instead of the item name.

If you specify 0 for Nth Item, the total number of matches will be returned instead. An example from our Colors table would be:

//echo -a $hfind(Colors, *ary*, 1, w)

Which will return "Gary".

See Also

More detailed information can be found at the pages for each hashtable-related command and identifier.