I'm trying to replace the elements of a list that equal to the keys of the hashmap with the corresponding values.
Here is what I tried:
#lang racket
(define my-hash (make-hash))
(hash-set! my-hash 'a 1)
(hash-set! my-hash 'b 2)
(hash-set! my-hash 'c 3)
(define (replace-all ht lst)
(hash-map ht
(lambda (key value)
(convert-list key value lst)))
)
(define (convert-list old_element new_element lst)
(cond [(equal? lst '()) '()]
[(not (list? lst)) (if (equal? old_element lst) new_element lst)]
[(list? (car lst)) (cons (convert-list old_element new_element (car lst)) (convert-list old_element new_element (cdr lst)))]
[else (if (equal? old_element (car lst)) (cons new_element (convert-list old_element new_element (cdr lst)))
(cons (car lst) (convert-list old_element new_element (cdr lst))))]
)
)
(replace-all my-hash '(a b c d '(a b)))
gives me '((a b 3 d '(a b)) (1 b c d '(1 b)) (a 2 c d '(a 2)))
. What I want is '(1 2 3 d'(1 2))
. How should I do that?
You're working backwards - instead of iterating over the table and trying to replace each key of it in turn, iterate over the nested list and replace elements that exist in the table. For example:
#lang racket
; Consider using hasheq instead if your keys are always going to be symbols
(define my-hash #hash((a . 1) (b . 2) (c . 3)))
(define (replace-all ht lst)
(cond
((hash-has-key? ht lst) ; Current lst is a key that exists in the hash table
; So return the value
(hash-ref ht lst))
((pair? lst) ; Current lst is a cons cell (Not list? so it works with improper lists too)
; Recurse on both the car and cdr and return a new pair
(cons (replace-all ht (car lst)) (replace-all ht (cdr lst))))
(else ; No match and it's an atom; return it.
lst)))
(replace-all my-hash '(a b c d '(a b)))