使用内置函数和映射修改方案中的列表

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

我正在尝试设计一个名为 changeList 的函数来修改方案中的列表。

该函数应删除 -1 和 +1 之间的每个数字(含两者)。对于每个大于 1 的数字,它应该用 10 倍的数字替换数字。对于每个小于 -1 的数字,它应该用倒数的绝对值替换数字。

这是我目前的代码

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

这是所需输出的示例

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

我能够评估 x 是否大于 1 以及 x 是否小于 -1,但是我在添加条件语句以评估值是否介于 -1 和 1 之间时遇到问题。我需要跳过那个值而不是输出它,我不知道该怎么做。

最好先去掉 [-1, 1] 范围内的数字:这就是 filter 派上用场的地方。之后,我们可以将 map 应用于过滤步骤的结果,实现所需的规则。这应该可以解决问题:

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

在 Racket 中,我们可以一步完成 filter-then-map 的习惯用法,而且效率也会更高:

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

无论哪种方式,它都按预期工作:

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

在普通的lisp中,人们会使用mapcan,在Racket中是append-map。 return 由给定 append-map 的函数编辑的结果必须 return 一个列表或 '().

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

总是,如果您想使用 map 但有时不应收集任何结果, 您可以在任何地方使用 append-map 并使用 '() 作为 return 值 被收藏了。