[racket] multi[set,hash] question
> Is there support in racket for hash tables where there could be a few (> 1)
> entries with the same key?
>
> Like std::multiset in C++
I'm not familiar with std:multiset and all it might do.
It's not hard in Racket to store a `list` of things as the value in a
hash table. Actually a `set` would be a better choice. So in
contract-ish notation:
(hash/c any/c (set/c any/c))
Then write a few small wrapper functions to do the equivalent of
`hash-set` and `hash-remove`, but taking into account the fact that
the hash values are `set`s.
Here's my quick attempt at such wrappers for both mutable and immutable:
#lang racket
;; Helpers for (hash/c any/c (set/c any/c))
(define (hash-set/multi h k v)
(hash-set h k (set-add (hash-ref h k (set)) v)))
(define (hash-remove/multi h k v)
(define s (set-remove (hash-ref h k) v))
(cond [(set-empty? s) (hash-remove h k)]
[else (hash-set h k s)]))
(define (hash-set/multi! h k v)
(hash-set! h k (set-add (hash-ref h k (set)) v)))
(define (hash-remove/multi! h k v)
(define s (set-remove (hash-ref h k) v))
(cond [(set-empty? s) (hash-remove! h k)]
[else (hash-set! h k s)]))
;; Usage
(displayln "mutable example:")
(define h (make-hash))
h
(hash-set/multi! h 'key "a")
h
(hash-set/multi! h 'key "b")
h
(hash-remove/multi! h 'key "a")
h
(hash-remove/multi! h 'key "b")
h
(displayln "immutable example:")
(for/fold ([h (for/fold ([h (hash)])
([v '("a" "b")])
(print h) (newline)
(hash-set/multi h 'key v))])
([v '("a" "b")])
(print h) (newline)
(hash-remove/multi h 'key v))