utils: Add hash-filter.
This commit is contained in:
parent
208dc12060
commit
73756d8974
1 changed files with 34 additions and 1 deletions
35
utils.rkt
35
utils.rkt
|
@ -55,7 +55,11 @@
|
|||
[#:combine (-> any/c any/c any/c)
|
||||
#:combine/key (-> any/c any/c any/c any/c)]
|
||||
#:rest (listof hash?)
|
||||
(and/c hash? immutable?))])
|
||||
(and/c hash? immutable?))]
|
||||
[hash-filter (->* (hash?)
|
||||
(#:predicate (-> any/c boolean?)
|
||||
#:predicate/key (-> any/c any/c boolean?))
|
||||
hash?)])
|
||||
;; Contracts
|
||||
(contract-out [variable-mapping? contract?]
|
||||
[string-variable-mapping? contract?]
|
||||
|
@ -624,6 +628,35 @@
|
|||
(check-equal? (hash-intersect h1 h3 #:combine -)
|
||||
'#hash((a . -6) (c . -5)))))
|
||||
|
||||
;;; Functionally filters a hash table: only keeps the key-value pairs
|
||||
;;; that satisfy a given criterion.
|
||||
;;;
|
||||
;;; The filtering criterion should be specified either via #:predicate
|
||||
;;; or #:predicate/key. #:predicate should be a function returning
|
||||
;;; a Boolean result given a value of the hash value. #:predicate
|
||||
;;; should be a function taking a key and the corresponding value.
|
||||
(define (hash-filter
|
||||
ht
|
||||
#:predicate [predicate #f]
|
||||
#:predicate/key [predicate/key
|
||||
(if predicate
|
||||
(λ (_ v) (predicate v))
|
||||
(error 'hash-filter))])
|
||||
(for/fold ([filtered-pairs (hash-clear ht)])
|
||||
([(k v) (in-hash ht)])
|
||||
(if (predicate/key k v)
|
||||
(hash-set filtered-pairs k v)
|
||||
filtered-pairs)))
|
||||
|
||||
(module+ test
|
||||
(test-case "hash-filter"
|
||||
(check-equal? (hash-filter (hash 'a 0 'b 1 'c 0)
|
||||
#:predicate (compose not zero?))
|
||||
#hash((b . 1)))
|
||||
(check-equal? (hash-filter (hash 'a 0 'b 1 'c 0) #:predicate/key
|
||||
(λ (k v) (and (eq? k 'b) (not (zero? v)))))
|
||||
'#hash((b . 1)))))
|
||||
|
||||
;;; =========
|
||||
;;; Functions
|
||||
;;; =========
|
||||
|
|
Loading…
Reference in a new issue