rassoc, rassoc-if, rassoc-if-not
rassoc, rassoc-if, rassoc-if-not Function
Syntax:
rassoc item alist &key key test test-not → entry
rassoc-if predicate alist &key key → entry
rassoc-if-not predicate alist &key key → entry
Arguments and Values:
item—an object.
alist—an association list.
predicate—a designator for a function of one argument that returns a generalized boolean. test—a designator for a function of two arguments that returns a generalized boolean. test-not—a designator for a function of two arguments that returns a generalized boolean. key—a designator for a function of one argument, or nil.
entry—a cons that is an element of the alist, or nil.
Description:
rassoc, rassoc-if, and rassoc-if-not return the first cons whose cdr satisfies the test. If no such cons is found, nil is returned.
If nil appears in alist in place of a pair, it is ignored.
Examples:
(setq alist ’((1 . "one") (2 . "two") (3 . 3)))
→ ((1 . "one") (2 . "two") (3 . 3))
(rassoc 3 alist) → (3 . 3)
(rassoc "two" alist) → NIL
(rassoc "two" alist :test ’equal) → (2 . "two")
(rassoc 1 alist :key #’(lambda (x) (if (numberp x) (/ x 3)))) → (3 . 3)
(rassoc ’a ’((a . b) (b . c) (c . a) (z . a))) → (C . A)
(rassoc-if #’stringp alist) → (1 . "one")
(rassoc-if-not #’vectorp alist) → (3 . 3)
See Also:
assoc, Section 3.6 (Traversal Rules and Side Effects)
Notes:
The :test-not parameter is deprecated.
The function rassoc-if-not is deprecated.
It is possible to rplaca the result of rassoc, provided that it is not nil, in order to “update” alist. The expressions
(rassoc item list :test fn)
and
(find item list :test fn :key #’cdr)
are equivalent in meaning, except when the item is nil and nil appears in place of a pair in the alist. See the function assoc.
Expanded Reference: rassoc, rassoc-if, rassoc-if-not
Reverse association list lookup
rassoc searches an alist by matching against the cdr (value) of each pair, rather than the car (key). It returns the entire pair, or NIL if not found.
(rassoc 2 '((a . 1) (b . 2) (c . 3)))
=> (B . 2)
(rassoc 99 '((a . 1) (b . 2) (c . 3)))
=> NIL
Finding a key by its value
rassoc is the reverse of assoc: use car on the result to get the key associated with a value.
(car (rassoc 'green '((apple . green) (banana . yellow) (cherry . red))))
=> APPLE
String values require a :test argument
Like assoc, the default test is eql, which does not work for string comparison.
(rassoc "two" '((2 . "two") (3 . "three")) :test #'equal)
=> (2 . "two")
(rassoc "two" '((2 . "two") (3 . "three")))
=> NIL
rassoc-if: search by predicate on the value
rassoc-if applies a predicate to the cdr of each pair.
(rassoc-if #'stringp '((1 . 100) (2 . "hello") (3 . "world")))
=> (2 . "hello")
(rassoc-if #'zerop '((a . 5) (b . 0) (c . 3)))
=> (B . 0)
Using :key for custom extraction
The :key function is applied to the cdr of each pair before testing.
(rassoc 3 '((a . (1 2 3)) (b . (4 5 6))) :key #'length)
=> (A 1 2 3)
Practical use: reverse lookup in a bidirectional mapping
rassoc enables reverse lookups in an alist used as a bidirectional map.
(let ((codes '((:us . "United States")
(:uk . "United Kingdom")
(:fr . "France"))))
;; Forward lookup
(cdr (assoc :uk codes))
;; Reverse lookup
(car (rassoc "France" codes :test #'equal)))
=> :FR