我试图自学球拍。我目前正在尝试编写一个函数来帮助理解嵌套列表。该函数采用嵌套列表和过程,并将过程应用于每个元素以生成新列表。一个例子:
(map-tree even? '(1 2 3 4)) => '(#f #t #f #t)
这是我到目前为止所得到的:
(define (map-tree proc tree)
(map-tree-aux tree proc '() ))
(define (map-tree-aux tree proc lst)
(if (null? tree)
lst
(if (list? tree)
(if (null? (cdr tree))
(if (number? (car tree))
(map-tree-aux (car tree) proc (append-end (proc (car tree)) lst))
(map-tree-aux (car tree) proc lst))
(if (number? (car tree))
(map-tree-aux (cdr tree) proc (append-end (proc (car tree)) (map-tree-aux (car tree) proc lst)))
(map-tree-aux (cdr tree) proc lst)))
lst)))
(define (append-end elem lst)
(append lst (list elem)))
虽然这适用于我提供的原始示例,但更复杂的示例不正确:
(map-tree even? '(1 (2 (3 (4))))) should be '(#f (#t (#f (#t)))), but is currently (#f #t #f #t).
我知道这只是一个问题"列出"在某个地方,但我有一个问题,找出如何做到这一点。
我的第一个想法是将list
过程应用于lst
如果树为空并且(car tree)
不是数字,但我得到了与我想要的相反(结果列表嵌套在相反的方向)。我非常感谢你的帮助。
谢谢!
答案 0 :(得分:1)
当迭代列表列表时,要检查的案例的一般想法是:
(null? lst)
,则执行某些操作 ... (not (pair? (car lst)))
,做其他事情 ...... (pair? (car lst))
, else ... Choosing the right construct也很重要,即。而不是嵌套if
语句,使用cond
或match
等是首选。
还要尽量避免在递归步骤中使用非常量时间过程(例如append
)来提高效率。
考虑到这些,创建有问题的函数的一种方法是简单地使用cons
来构建新列表,同时保留旧的结构,如下所示:
(define (my-map pred lst)
(cond
((null? lst) '())
((not (pair? (car lst)))
(cons (pred (car lst))
(my-map pred (cdr lst))))
(else
(cons (my-map pred (car lst))
(my-map pred (cdr lst))))))
您可以使用match
代替cond
编写相同的功能:
(define (my-map pred lst)
(match lst
['() '()]
[(cons (? pair?) b)
(cons (my-map pred (car lst))
(my-map pred (cdr lst)))]
[(cons a b)
(cons (pred (car lst))
(my-map pred (cdr lst)))]))
您还可以构建一个执行此操作的尾递归函数:
(define (my-map pred lst)
(let loop ((lst lst)
(acc '()))
(cond
((null? lst)
(reverse acc))
((not (pair? (car lst)))
(loop (cdr lst) (cons (pred (car lst)) acc)))
(else
(loop (cdr lst) (cons (loop (car lst) '()) acc))))))
请注意,在基本情况下返回(reverse acc)
,因为在累加器acc
中构建的列表与原始列表lst
的顺序相反。为避免这种情况,我们可以将此函数修改为累积延续:
(define (my-map pred lst)
(let loop ((lst lst)
(acc identity))
(cond
((null? lst)
(acc '()))
((not (pair? (car lst)))
(loop (cdr lst) (lambda (r)
(acc (cons (pred (car lst)) r)))))
(else
(loop (cdr lst)
(lambda (r)
(acc (cons (loop (car lst) identity) r))))))))
对于所有情况,您将拥有:
(my-map even? '(1 2 3 4 5 7))
=> '(#f #t #f #t #f #f)
(my-map even? '(1 (2 (3 (4 (5 (7)))))))
=> '(#f (#t (#f (#t (#f (#f))))))