Emacs Lisp: Hash Table

Master emacs+lisp, benefit for life. Testimonials. Thank you for support.
, , …,

This page is a tutorial on emacs lisp hash table.

Hash Table, Associative Array/List, Dictionary

One very useful datatype is a list of pairs. ⁖ ((key1 value1) (key2 value2) (key3 value3) …). Depending on the language or implementation, it may be called {hash table, keyed list, dictionary}.

Here's how hash table looks like in different languages:

# ruby
mydata = {:joe => 4, :jane => 5, :vicky => 7}
# Python
mydata = {"joe":4, "jane":5, "vicky":7}
# PHP
$mydata = array("joe"=> 4, "jane"=> 5, "vicky"=> 7);
# perl
%mydata = ("joe"=> 4, "jane"=> 5, "vicky"=>7);

Emacs lisp has 2 types of keyed list.

What's the Difference Between Alist and Hash Table?

In modern languages since about 2005, the difference between hash table and alist are getting fuzzy, depending on the language. But basically:

Hash Table in Emacs Lisp

To create a hash table, use (make-hash-table :test 'equal).

Here's a complete code that shows how to create a hash table, then add, change, remove, entries:

(let (myHash val)

  ;; create a hash table
  (setq myHash (make-hash-table :test 'equal))

  ;; add entries
  (puthash "joe" "19" myHash)
  (puthash "jane" "20" myHash)
  (puthash "carrie" "17" myHash)
  (puthash "liz" "21" myHash)

  ;; modify a entry's value
  (puthash "jane" "16" myHash)

  ;; remove a entry
  (remhash "liz" myHash)

  ;; get a entry's value
  (setq val (gethash "jane" myHash))

  (message val) ; print it
)

In the above example, the entry's keys and values are both “string” data type. However, elisp's hash table can have any lisp datatype as the key or value.

When we create a hash table, we used :test 'equal to let elisp know that the function equal should be used when testing whether a key exists. If your keys are other lisp data type, you need to specify which equality functon emacs should use to test if a key exist. The available value for :test are 'eql, 'eq, 'equal. (You can also define your own equality test.)

Count Length

To get a count of entries in hash table, use (hash-table-count myHash).

Remove All Entries

To clear all entries in a hash table, use (clrhash myHash).

Check If a Key Exists

To check if a key exists, use the (gethash myKey myHash). If it exists, its value is returned, else nil. Example:

(let (myHash)
  (setq myHash (make-hash-table :test 'equal))
  (puthash 'joe "19" myHash)

  (gethash 'vicky myHash) ; ⇒ nil
)

gethash has a optional third parameter. If the key does not exist, that value is returned.

Apply a Function to All Key-Value Pairs

To apply a function to all entries in a hash table, use (maphash myfun myHashtable). The function “myfun” must take 2 arguments, key and value. For example, if you want a list of all keys, you can write a function that puts the key into a list, then print out the list. We show several examples below.

Get All Keys

In emacs 24.4, use hash-table-keys from (require 'subr-x)

;; emacs 24.4, example of getting all keys from a hash table

;; creating a hash
(setq myHash (make-hash-table :test 'equal))
(puthash "joe" "19" myHash)
(puthash "jane" "20" myHash)

;; get all keys
(require 'subr-x)
(hash-table-keys myHash) ; ⇒ ("jane" "joe")

In emacs before 24.4, you can use a maphash with a function that pulls the keys into a list.

(defun get-hash-keys (hashtable)
  "Return all keys in hashtable."
  (let (allkeys)
    (maphash (lambda (kk vv) (setq allkeys (cons kk allkeys))) hashtable)
    allkeys
  )
)

With this function, you can use it like this: (get-hash-keys hashtable).

Get All Values

in emacs 24.4, use hash-table-values from (require 'subr-x)

;; emacs 24.4, example of getting all keys from a hash table

;; creating a hash
(setq myHash (make-hash-table :test 'equal))
(puthash "joe" "19" myHash)
(puthash "jane" "20" myHash)

;; get all keys
(require 'subr-x)
(hash-table-values myHash) ; ⇒ ("20" "19")

for emacs before 24.4:

(defun get-hash-values (hashtable)
  "Return all values in HASHTABLE."
  (let (allvals)
    (maphash (lambda (kk vv) (setq allvals (cons vv allvals))) hashtable)
    allvals
  )
)

Print All Entries Sorted by Key

Here's a example how you can print out all entries in a hash table by sorted key.

First, we define a function that turns a hash table into a list.

(defun hash-to-list (hashtable)
  "Return a list that represent the HASHTABLE."
  (let (myList)
    (maphash (lambda (kk vv) (setq myList (cons (list kk vv) myList))) hashtable)
    myList
  )
)
;; example of turning a hash table into list then sort it
(let (myHash myList)

  ;; add items to the hash
  (setq myHash (make-hash-table :test 'equal))
  (puthash "joe" "19" myHash)
  (puthash "jane" "20" myHash)
  (puthash "carrie" "17" myHash)
  (puthash "liz" "21" myHash)

  ;; get the hash table into a list
  (setq myList (hash-to-list myHash))

  ;; sort and print it out
  (sort myList (lambda (a b) (string< (car a) (car b))))
)

;; prints (("carrie" "17") ("jane" "20") ("liz" "21") ("joe" "19"))

Warning: elisp's sort function is destructive. Once sort is used on a variable, that variable's value is essentially destroyed. (the sorted result is returned.) If you want to keep the variable, make a copy first.

(info "(elisp) Rearrangement")

Hash Table with Lisp Objects

Elisp's hash table's key or value can be any lisp object. Also, you can define your own equality test, as well as providing few other parameters when creating a hash table. For detail, see elisp manual.

(info "(elisp) Hash Tables")

Emacs ♥

Like what you read?
Buy Xah Emacs Tutorial
or share some
blog comments powered by Disqus