Sam Daly
Sam Daly

Reputation: 51

Modifying a list in scheme using built-in functions and map

I'm trying to design a function called changeList that modifies a list in scheme.

The function should drop each number between -1 and +1 inclusive. For each number greater than 1 it should replace the number with 10 times the number. For each number smaller than -1 it should replace the number with the absolute value of the reciprocal.

Here's the code I have so far

(define (changeList x) (map (lambda (x) (if (> x 1) (* x 10) (* (/ 1 x) -1))) x))

Here's an example of the desired output

(changeList '(0 -2 3 -4 1)) -> '( 1/2 30 1/4 )

I'm able to evaluate if x if greater than 1 and if x is smaller than -1, however I'm having issues adding the conditional statements to evaluate if the value is between -1 and 1 inclusively. I need to skip that value and not output it which I'm not sure how to do it.

Upvotes: 1

Views: 537

Answers (2)

Óscar López
Óscar López

Reputation: 236170

It'd be better if first we get rid of the numbers in the range [-1, 1]: that's where filter will come in handy. After that, we can apply map to the result of the filtering step, implementing the required rules. This should do the trick:

(define (changeList lst)
  (map (λ (x) (if (> x 1) (* 10 x) (/ -1 x)))
       (filter (λ (x) (or (< x -1) (> x 1)))
               lst)))

In Racket we can do the filter-then-map idiom in a single step, and it'll also be more efficient:

(define (changeList lst)
  (filter-map (λ (x) (and (or (< x -1) (> x 1))
                          (if (> x 1) (* 10 x) (/ -1 x))))
              lst))

Either way, it works as expected:

(changeList '(0 -2 3 -4 1))
=> '(1/2 30 1/4)

Upvotes: 1

Gwang-Jin Kim
Gwang-Jin Kim

Reputation: 10163

In common lisp, one would use mapcan, which is append-map in Racket. The results returned by the function given to append-map must return a list or '().

(define (changeList lst)
  (append-map (lambda (x)
                (cond ((> x 1) (list (* x 10)))
                      ((< x -1) (list (* (/ 1 x) -1)))
                      (else '())))
              lst))

Always, if you want to use a map but sometimes no results should be collected, you can use append-map and use '() as return value everywhere nothing should be collected.

Upvotes: 0

Related Questions