James Lalonde
James Lalonde

Reputation: 79

Beginner scheme how to replace a string into a list?

;; An association list (al) is either

;; empty or

;; (cons (list k v) alst), where

;; k is a nat (the key),

;; v is a string (the value), and

;; alst is an association list (al)

updatestring takes an association list, a number (findnum) and a string (newstring) and if there is a number the same as findnum in the association list, then it replaces the string in the list with newstring.

(check-expect(updatestring empty 3 "hi") (list (list 3 "hi")))
(check-expect(updatestring (list (list 1 "hi")(list 5 "wow")) 5 "new")(list (list 1 "hi")(list 5 "new")))
(check-expect(updatestring (list (list 1 "hi")(list 5 "wow")) 2 "nice")(list (list 2 "nice") (list 1 "hi")(list 5 "wow")))

I'm having trouble with the code as this is what I have.

(define (al-update alst akey avalue)
 (cond
  [(empty? alst) (list (list akey avalue))]
  [(= (first(first alst)) akey) (al-update (rest alst) akey avalue)]
  [else (list(list akey avalue alst))]))

The problem is that my code returns

(list (list 5 "new" (list (list 1 "hi") (list 5 "wow"))) instead of (list (list 1 "hi") (list 5 "new"))

and

(list(list 2 "nice" (list (list 1 "hi") (list 5 "wow")))) instead of (list (list 2 "nice") (list 1 "hi")(list 5 "wow")))

Any tips and answers would be very much appreciated thanks!

Upvotes: 0

Views: 498

Answers (2)

grgizem
grgizem

Reputation: 310

It says "if there is a number the same as findnum in the association list, then it replaces the string in the list with newstring", but in your example if the given number does not exist you add that into the list.

(check-expect (updatestring (list (list 1 "hi") (list 5 "wow")) 2 "nice")
              (list (list 2 "nice") (list 1 "hi") (list 5 "wow")))
(check-expect(updatestring empty 3 "hi") (list (list 3 "hi")))

Code and the examples (tests) should be these:

(define (al-update alst akey avalue)
 (cond
  [(empty? alst) empty]
  [(= (first (first alst)) akey) (cons (list (first (first alst)) avalue)
                                       (al-update (rest alst) akey avalue))]
  [else (cons (first alst) (al-update (rest alst) akey avalue))]))


(check-expect (updatestring empty 3 "hi") empty)
(check-expect (updatestring (list (list 1 "hi") (list 5 "wow")) 5 "new")
              (list (list 1 "hi") (list 5 "new")))
(check-expect (updatestring (list (list 1 "hi") (list 5 "wow")) 2 "nice")
              (list (list 1 "hi") (list 5 "wow")))
(check-expect (updatestring (list (list 1 "hi") (list 5 "wow") (list 2 "bad")) 2 "nice")
              (list (list 1 "hi") (list 5 "wow") (list 2 "nice")))

By the way "car" is equivalent to "first" and "cdr" is "rest".

Upvotes: 0

GoZoner
GoZoner

Reputation: 70265

Your recursive structure needs to be something like this:

(define (al-update alist akey avalue)
  (if (empty? alist)                                 ; base, end recusion
      '()
       (cons (let ((key+value (first alist)))        ; element, one-by-one
               (if (= ...)
                    ...
                    ...))
             (al-update (rest alist) akey avalue)))) ; recursion

In your code there are a number of problems. The else clause needs to recurse over the rest of the list. In the = clause you need to do the substitution and recurse. In my code above, I combined the two clauses that recurse.

Upvotes: 1

Related Questions