如何使用列表中的元素构造特定形状的树

时间:2014-11-30 00:02:00

标签: scheme

给定一个s表达式'((a . b) . (c . d))和一个列表'(e f g h),我如何遍历s-expression创建一个具有相同形状的s-expression,但是从列表中取出了元素?例如,对于上面的s表达式和列表,结果将是'((e . f) g . h)

3 个答案:

答案 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)