给定一个s表达式'((a . b) . (c . d))
和一个列表'(e f g h)
,我如何遍历s-expression创建一个具有相同形状的s-expression,但是从列表中取出了元素?例如,对于上面的s表达式和列表,结果将是'((e . f) g . h)
?
答案 0 :(得分:1)
我假设您要创建一个新的s表达式,其s-expression的形状与第一个参数相同,但是使用第二个参数列表的元素。
如果这是正确的,这里有一个可能的解决方案,使用列表来保存我们在替换列表中的点和Racket的begin0
以保持列表更新(如果您在解释器中没有使用{{1}如Chris和Joshua在评论中所建议的那样:
let
例如:
(define (transform sexp lst)
(let loop ((sexp sexp)) ; the s-expression list to be traversed
(cond ((null? sexp) '()) ; if it's empty, we're finished
((not (pair? sexp)) ; if it's an atom
(begin0 ; then (alternatively: use a `let`)
(car lst) ; return first element in replacements list
(set! lst (cdr lst)))) ; and update replacements to next element
(else ; otherwise advance recursion
(cons (loop (car sexp)) ; over both the `car` part of input
(loop (cdr sexp))))))) ; and the `cdr` part
答案 1 :(得分:1)
从左到右遍历一对树并不是特别困难,因为汽车和 cdr 让你到达双方,利弊可以把事情重新组合在一起。像这样的问题中棘手的部分是"替换"在树的右侧,您需要知道在处理树的左侧时使用了多少可用输入。所以,这是一个程序重塑,它带有一个模板(一个带有你需要的形状的树)和一个列表要在新树中使用的元素。它将新树和列表中的任何剩余元素作为多个值返回。这意味着在一对的递归调用中,您可以轻松获得新的左右子树以及其余元素。
(define (reshape template list)
;; Creates a tree shaped like TEMPLATE, but with
;; elements taken from LIST. Returns two values:
;; the new tree, and a list of any remaining
;; elements from LIST.
(if (not (pair? template))
(values (first list) (rest list))
(let-values (((left list) (reshape (car template) list)))
(let-values (((right list) (reshape (cdr template) list)))
(values (cons left right) list)))))
(reshape '((a . b) . (c . d)) '(e f g h))
;=> ((e . f) g . h)
;=> ()
(reshape '((a . b) . (c . d)) '(e f g h i j k))
;=> ((e . f) g . h)
;=> (i j k) ; leftovers
答案 2 :(得分:0)
解决方案类似于我的previous answer:
(define (transform sxp lst)
(let loop ((sxp sxp))
(cond ((null? sxp) sxp)
((pair? sxp) (cons (loop (car sxp)) (loop (cdr sxp))))
(else (begin0 (car lst) (set! lst (cdr lst)))))))
然后
> (transform '((a . b) . (c . d)) '(e f g h))
'((e . f) g . h)