Emacs Lisp: Association List
Association List (aka alist) is a value type in Emacs Lisp.
Association List is a List , where each element is a Cons Pair , like this
(cons key val)
- In each cons pair, the key and value can be any value type.
- Items in Association List can have duplicate keys, and order is maintained.
Tip: dot notation for cons
when creating a association list, For example
(list
(cons k1 v1)
(cons k2 v2)
)
is often written as
'(
(k1 . v1)
(k2 . v2)
)
if you do not need to evaluate the items. [see Emacs Lisp: Quote and Dot Notation]
What is the Difference Between Association List and Hash Table?
- Association List is ordered. Hash Table items are not.
- Association List can have duplicate keys. Hash Table keys are unique.
- Association List access time is proportional to number of items. Hash Table is constant time to access any item regardless of number of items.
- Association List entries are hard to modify. As a list, it's designed to only add or drop first item of the list. Hash Table entries are designed to be modified, or added or deleted.
Create a Alist
Using string as key:
;; example of association list (setq xx (list (cons "aa" 23) (cons "bb" 24) (cons "cc" 33))) ;; dot notation (setq xx '(("aa" . 23) ("bb" . 24) ("cc" . 33)))
Using Symbol as key:
;; example of association list ;; where keys are symbols, values are numbers (setq xx (list (cons 'aa 23) (cons 'bb 24) (cons 'cc 33))) ;; dot notation (setq xx '((aa . 23) (bb . 24) (cc . 33)))
Symbol Key vs String Key
Usually,
Symbol
is used for key.
eq
tests if 2 symbols are equal.
You can also use
String
as key. To compare if 2 string is equal, equal
works.
Some functions for alist use eq
to test existence of key, and others use equal
.
Some lets you specify a function for equality test.
So, it is important to know:
- What datatype you are using as key in your alist
- Which equality test is used by a specific alist function.
Get Value by Key
alist-get
-
(alist-get key alist &optional default remove testfn)
Return the first value of the key. If no exist, return default or nil.The remove should be nil. (it is used in advanced situation with Place Expression . You shouldn't use that for beginning lisp.)
key existence is checked by testfn (must be a symbol of function). Default to
eq
. [see Emacs Lisp: Test Equality](setq xx '(("aa" . 23) ("bb" . 24) ("cc" . 33))) ;; get the value with key "bb". if not found, return 999. use string-equal for comparison (alist-get "bb" xx 999 nil 'string-equal) ;; 24 (alist-get "dd" xx 999 nil 'string-equal) ;; 999
(setq xx '((aa . 23) (bb . 24) (cc . 33))) ;; get the value with symbol key bb. if not found, return 999 (alist-get 'bb xx 999) ;; 24 (alist-get 'dd xx 999) ;; 999
Get Pair by Key
assoc
-
(assoc key alist)
Return the first pair with the key. If no exist, return nil. (key existence is checked byequal
. [see Emacs Lisp: Test Equality] )(setq xx '(("aa" . 23) ("bb" . 24) ("cc" . 33))) ;; get the pair with key "bb" (assoc "bb" xx) ; return ("bb" . 24)
assq
-
(assq key alist)
same asassoc
except key is checked byeq
. Use this if all keys are Symbols [see Emacs Lisp: Test Equality](setq xx '((aa . 23) (bb . 24) (cc . 33))) (assq 'aa xx)
Check If a Key Exist
Use assoc
or assq
.
Get Pair by Value
You can search alist by value.
rassoc
-
(rassoc val alist)
Return the first pair that has specific value. Else return nil. Test is done byequal
. [see Emacs Lisp: Test Equality](setq xx '(("aa" . 23) ("bb" . 24) ("cc" . 33))) ;; get the pair with value 24 (rassoc 24 xx) ; return ("bb" . 24)
rassq
-
(rassq value alist)
same asrassoc
except value is compared usingeq
. [see Emacs Lisp: Test Equality]
Add a Element
Add a Pair to Front
Add a element to the front. Use push
(setq xx '(("aa" . 23) ("bb" . 24) )) ;; add a element (push '("cc" . 33) xx)
Add a Pair If Key No Exist
(setq xx '(("aa" . 23) ("bb" . 24) )) (when (not (assoc "cc" xx)) (push '("cc" . 33) xx))
Add a Pair If Pair No Exist
(defun xah-add-asso-if-pair-no-exist (ConsPair Alist) "Add ConsPair to Alist if the ConsPair not exist. Both key and value of ConsPair are checked. With `equal'. Return new Alist. Version 2021-12-03" (let* ((xkey (car ConsPair)) (xval (cdr ConsPair)) (xresult (assoc xkey Alist))) (if (and xresult (equal xval (cdr xresult))) nil (push ConsPair Alist)) Alist )) ;; HHHH--------------------------------------------------- ;; sample usage (xah-add-asso-if-pair-no-exist (cons "aa" 23) (list (cons "aa" 23) (cons "bb" 24))) ;; not added (xah-add-asso-if-pair-no-exist (cons "aa" 99) (list (cons "aa" 23) (cons "bb" 24))) ;; added ;; HHHH--------------------------------------------------- ;; sample usage with dot notation (xah-add-asso-if-pair-no-exist '("aa" . 23) '(("aa" . 23) ("bb" . 24))) ;; not added (xah-add-asso-if-pair-no-exist '("aa" . 99) '(("aa" . 23) ("bb" . 24))) ;; added
Delete Pairs by Key
assoc-delete-all
-
(assoc-delete-all KEY ALIST &optional TEST)
Delete all elements that has key KEY. Keys are checkd by TEST. Defaults toequal
. Return the modified alist. Elements of ALIST that are not conses are ignored.(setq xx '(("aa" . 23) ("bb" . 24) )) (setq xx (assoc-delete-all "bb" xx))
assq-delete-all
-
same as
assoc-delete-all
but useseq
for testing key.
More Alist Functions
Note, Association List is a List , any function that works on list also works on Association List.
[see Emacs Lisp: Sequence Functions]
There are many more specialized function for alist. See
Association Lists (ELISP Manual)
Lisp Data Structure
List
- Cons Pair
- Quote and Dot Notation
- Proper List
- List
- Create List
- List, Get Elements
- Modify List
- Check Element Exist in List
- Remove Elements in List
- Backquote Reader Macro