【问题标题】:How to manually flatten a list in Racket (Scheme)如何在 Racket 中手动展平列表(方案)
【发布时间】:2015-04-29 11:53:46
【问题描述】:

如果不使用球拍内置的展平功能,如何展平列表?

我明白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)))

【问题讨论】:

  • 什么意思?第一个flatten 函数使用Racket 的flatten 函数,它递归地调用自己。该实现几乎是独立的,但不正确 - 请参阅我的答案。另外,尽量避免使用变异操作 (set!),这不是我们在 Scheme 中编写大多数函数的方式。

标签: scheme racket flatten list-processing


【解决方案1】:

显示的第一个实现是独立的,但不正确,它没有调用 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))))

【讨论】:

  • 对不起,我一定误解了我正在阅读的代码。我已经编程了几个小时,有时事情会在一段时间后变得扭曲。我在输出中得到了一个报价,这是什么意思? > (my-flatten '(1 2 '(3 4) 5)) '(1 2 quote 3 4 5) -- 抱歉我对 Racket 的理解不好,我对此很陌生
  • @JamesCombs 删除最里面的引号,这是导致问题的原因
  • 我认为list?#!racket 中可能是O(1),但使用pair? 也将支持点列表(至少是最后一个版本)。
  • @ÓscarLópez 感谢您的所有帮助,如果我可以再一次戳您的大脑以完全理解其本质...在 append 函数内部,执行递归时,它是否执行两个递归语句同时构建 2 个不同的堆栈帧?对我来说,这将是唯一可行的解​​释,否则第一个递归语句只会继续调用列表的第一个元素,而永远不会达到基本情况。这是正确的吗?
  • @JamesCombs 递归调用按顺序执行,但 append 仅在两者都从各自的调用返回时才执行。显然已经达到了基本情况,为什么不呢?如果这个答案对你有帮助,请不要忘记accept它,只需单击其左侧的复选标记;)
猜你喜欢
  • 2016-01-25
  • 2019-11-26
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
  • 2016-09-07
  • 2022-01-09
  • 2013-04-24
  • 1970-01-01
相关资源
最近更新 更多