如何在Racket中手动压平列表(Scheme)

时间:2015-02-26 22:10:03

标签: scheme racket flatten list-processing

怎么可以在不使用内置的flatten函数来展平列表?

据我所知,flatten的默认实现是

(define (flatten lst)
  (cond 
    ((null? list)
      empty)
    ((list? (car lst))
      (append (flatten (car lst)) (flatten (cdr lst))))
    (else
      (cons (car lst) (flatten (cdr lst))))))

但我不完全确定如何不使用flatten功能,因为我不知道它是如何在幕后工作。除了这段代码的实现之外,我找不到对此的良好解释。请有人解释一下

这是我非常糟糕的尝试,我几乎一无所知,因为这甚至不是很接近而且不会运行....

(define acc null)
(define (my-flatten lst)
  (cond
    [(null? lst) null]
    [(list? (car lst)) (help-flatten (car lst)) (append (cdr lst) acc)]
    [else (append (car lst) acc) (my-flatten (cdr lst))]))

(define (help-flatten subLst)
  (if (null? subLst)
      (set! acc null)
      (append (car subLst) acc))
  (help-flatten (cdr subLst)))

1 个答案:

答案 0 :(得分:5)

显示的第一个实现是自包含但不正确的,并且它没有调用Racket的内置flatten - 它只是递归地调用自身,重命名它以查看我的意思是说。这是一个固定版本:

(define (my-flatten lst)
  (cond ((null? lst) empty) ; you wrote `list` instead of `lst`
        ((pair? (car lst))  ; it's more efficient if we use `pair?`
         (append (my-flatten (car lst)) (my-flatten (cdr lst))))
        (else (cons (car lst) (my-flatten (cdr lst))))))

或者更简单一点:

(define (my-flatten lst)
  (cond ((null? lst) '())
        ((pair? lst)
         (append (my-flatten (car lst)) (my-flatten (cdr lst))))
        (else (list lst))))