Filter alist keys

Problem

You have an association list and you want a copy with only the specified keys.

Solution

Assuming no duplicate keys

``````(define (match value)
(lambda (x)
(equal? x value)))

(define (alist->subset keys alist)
(let iter ((alist alist) (keys keys) (result '()))
(if (or (null? alist) (null? keys))
(reverse result)
(let* ((pair (car alist)) (key (car pair)))
(if (member key keys)
(let ((keys (remove (match keys) keys)))
(iter (cdr alist) keys (cons pair result)))
(iter (cdr alist) keys result))))))
``````

Credit: Jakub T. Jankiewicz

It uses the `remove` procedure from another recipe.

Handling duplicate keys

``````(define (alist->subset keys alist)
(let loop ((alist alist) (new-alist '()))
(if (null? alist) (reverse new-alist)
(loop (cdr alist)
(let ((pair (car alist)))
(if (member (car pair) keys)
new-alist
(cons pair new-alist)))))))
``````

Credit: Lassi Kortela

Usage

``````(define alist '((foo . 10) (bar . 20) (baz . 30) (quux . 40)))

(alist->subset '(quux foo) alist)
;; ==> ((foo . 10) (quux . 40))
``````

Back to the Scheme Cookbook