How to match hash table values ​​(racket)

I want to map a function over values ​​in a hash table, for example:

(hash-map add1 (hash "apple" 1 "pear" 2)) => #hash(("apple" . 2) ("pear" . 3)) 

Is there a library for this? It would be nice to have one that worked on immutable hedients too.

I watched PlaneT but saw nothing there.

Now, if this really does not exist, I will continue it and write. What would be etiquette to get it on the racket? I just put it on github and add it to the standard library (and documents!) And send a transfer request? Or should I first make it a T plane, and then ask him to be moved? I would like to help, but I just don’t know what this “right” way is.

+4
source share
4 answers

There is a hash map, but it returns a list [ 1 ]

You need to write your own hash-map to do exactly what you want.

 #lang racket (define (new-hash-map fh) (make-immutable-hash (hash-map h (λ (kv) (cons k (fv)))))) (new-hash-map add1 (hash "apple" 1 "pear" 2)) ; => '#hash(("pear" . 3) ("apple" . 2)) 

Another form that may interest you is / hash [ 2 ]:

 #lang racket (define (new-hash-map2 fh) (for/hash ([(kv) (in-hash h)]) (values k (fv)))) (new-hash-map2 add1 (hash "apple" 1 "pear" 2)) ; => '#hash(("pear" . 3) ("apple" . 2)) 

If you think this functionality should be included in Racket, patches are welcome! The best way to contribute is to fork out github and send a pull request.

+5
source

In Racket, you can use a higher-order hash-map procedure, which usually returns a list with the values ​​obtained as a result of applying the procedure obtained as a parameter, but can be adapted to change the map in place. For instance:

 (define h (make-hash)) (hash-set! h "apple" 1) (hash-set! h "pear" 2) h => '#hash(("pear" . 2) ("apple" . 1)) 

The trick goes through lambda with the corresponding functionality:

 (hash-map h (lambda (key value) (let ((newval (add1 value))) (hash-set! h key newval) newval))) h => '#hash(("pear" . 3) ("apple" . 2)) 

For a more general solution, try this implementation:

 (define (mutable-hash-map! hash proc) (hash-map hash (lambda (key value) (hash-set! hash key (proc value)))) (void)) 
+2
source

You can iterate over hash table values ​​using in-hash-values and use the usual for loops to map them. The in-hash-values function takes a hash and returns a sequence of values ​​that can then be traversed using a for loop.

Example:

 (for/list ([elt (in-hash-values (hash "apple" 1 "pear" 2))]) (add1 elt)) 

Similarly, you can use sequence-map , although what you get is a different sequence, not a list:

 (sequence-map add1 (in-hash-values (hash "apple" 1 "pear" 2))) 
+1
source

Since hash-map creates a list that is not needed here, I would prefer to use a hash-for-everyone .

 (define (hash-update-all! h func) (hash-for-each h (lambda (kv) (hash-set! hk (func v))))) (define table (make-hash '((a . 1) (b . 2) (c . 3)))) (hash-update-all! table (curry * 100)) table ==> '#hash((c . 300) (a . 100) (b . 200)) 

Edit: I forgot that for can handle the hash table:

 (define (hash-update-all! h func) (for ([(kv) h]) (hash-set! hk (func v)))) (hash-update-all! table (curryr / 10)) table ==> '#hash((c . 30) (a . 10) (b . 20)) 
+1
source

All Articles