Hash tables

Author: Adrian Perez <aperez@igalia.com>
Copyright: 2008-2009 Igalia S.L.
License:GPL3

Abstract

Efficient dictionary-like structures i.e. a hash table.

Contents

Discussion

A hash table is a data structure which stores a set of (key, value) pairs in a way that enables for fast lookup of values when the keys are known. Those hash tables are used mainly with string keys and values, so they are sometimes called dictionaries as well.

Usage

A hash table can be accessed by using its unique identifier. New identifiers can be obtained using hash_new, and albeit they are regular strings and can be printed usually you do not need to know about them:

(bill) use data/hash
(bill) h=$(hash_new)
(bill) echo $h
:bill:0709bd8abbe7139f40dd48004e85a5ea00dd4bd3:

Now you can use the hash table, the basic functions for this are hash_set and hash_get:

(bill) hash_set $h firstname 'John'
(bill) hash_set $h lastname  'Doe'
(bill) hash_set $h email     'john@doe.org'
(bill) printf '%s %s <%s>\n' \
  ...)   "$(hash_get $h firstname)" \
  ...)   "$(hash_get $h lastname)" \
  ...)   "$(hash_get $h email)"
John Doe <john@doe.org>

We can check whether a key is present in a hash table using hash_has, which is nice to do checking. Note that hash_get will return an empty string and have a non-zero exit status:

(bill) hash_has $h email && echo Yes || echo No
Yes
(bill) hash_has $h age && echo Yes || echo No
No
(bill) v=$(hash_get $h age)
(bill) echo "code $?, value '$v'"
code 1, value ''

Finally, you can obtain a array of keys present in the hash table using hash_keys_escaped. Once you are done using a table, do not forget to use hash_clear on it:

(bill) keys=( $(hash_keys_escaped $h) )
(bill) echo "Keys: ${keys[*]}"
Keys: lastname firstname email
(bill) hash_clear $h
(bill) echo "Keys: ${keys[*]}"
Keys:

Acceptable values

Keys can be any string which can be represented in bash source code. You can even use “funny” keys containing escape and control characters as long as you do not try to iterate over keys containing them.

Warning

Use only printable characters for hash table keys when it is needed to iterate over the keys of a hash table using hash_keys_iter, hash_keys or hash_keys_escaped.

Nesting

As hash table identifiers are strings, you can use them as values of another hash table, thus creating nested tables:

(bill) outer=$(hash_new)
(bill) inner=$(hash_new)
(bill) hash_set $outer subtable $inner
(bill) hash_set $inner value 'I am inside inner'
(bill) hash_get $(hash_get $outer subtable) value
I am inside inner

This way complex data structures can be created. The syntax used to create them is not very pretty, but at least it is possible.

Functions

hash_new

hash_new

Creates a new hash table. Returns a has table identifier which is needed as first argument to all the other functions of the module.

hash_set

hash_set hash_id key value

Associates a key with a value. The hash_id parameter must be an identifier obtained with hash_new.

See also: hash_get, hash_has.

hash_get

hash_get hash_id key

Gets the value associated with a key. The hash_id parameter must be an identifier obtained with hash_new. The exit status is non-zero when an element is not found.

See also: hash_get, hash_has.

hash_del

hash_del hash_id key

Deletes a (key, value) pair from a hash table. The hash_id parameter must be an identifier obtained with hash_new.

See also: hash_set, hash_has, hash_clear.

hash_has

hash_has hash_id key

Checks whether a given key is set in a hash table. The hash_id parameter must be an identifier obtained with hash_new. The exit status is zero when the keys exists, and non-zero otherwise.

See also: hash_set.

hash_keys_iter

hash_keys_iter hash_id callback

Iterates over all keys of the given hash table hash_id. The callback will be called with the hash_id as first argument

Warning

Do not add or remove keys while iterating over the elements, behaviour is undefined.

See also: hash_keys_escaped, hash_keys.

hash_keys

hash_keys hash_id

Gathers all keys of a given hash table and print one key per line. It may be better to use hash_keys_escaped if you want to save the key list into an array.

See also: hash_keys_escaped, hash_keys_iter.

hash_keys_escaped

hash_keys_escaped hash_id

Gathers all keys of a given hash table and print one key per line. Unlike hash_keys, elements are escaped so you can reuse the output for gathering the key names into an array:

h=$(hash_new)
for i in $(seq 10) ; do
    hash_set $h "key $i" "value $i"
done
h_heys=( $(hash_keys_escaped $h) )

See also: hash_keys, hash_keys_iter.

hash_clear

hash_clear hash_id

Empties a hash table. The hash_id parameter must be a valid identifier obtained with hash_new.

See also: hash_new, hash_set, hash_del.