【问题标题】:Flatten a list using only the forms in "The Little Schemer"仅使用“The Little Schemer”中的表格来展平列表
【发布时间】:2011-11-10 22:19:39
【问题描述】:

我正在通过 The LIttle Schemer 学习 Scheme(作为一名老 C 程序员),作为练习,我尝试编写一个过程来使用 The Little Schemer 中的表单来展平列表;即definelambdacondcarcdrandor 等,但不是append。我认为这很容易,但我无法提出解决方案。我该怎么做?

【问题讨论】:

    标签: scheme the-little-schemer


    【解决方案1】:

    我有一个仅使用“第一原则”操作且高效的版本(与基于append 的解决方案不同,不需要多次通过任何列表)。 :-)

    它通过定义两个简单的构建块(foldreverse),然后在它们之上定义 flatten(及其助手,reverse-flatten-into)来做到这一点(并注意每个函数只是一个或两个行长):

    ;; Similar to SRFI 1's fold
    (define (fold1 kons knil lst)
      (if (null? lst)
          knil
          (fold1 kons (kons (car lst) knil) (cdr lst))))
    
    ;; Same as R5RS's reverse
    (define (reverse lst)
      (fold1 cons '() lst))
    
    ;; Helper function
    (define (reverse-flatten-into x lst)
      (if (pair? x)
          (fold1 reverse-flatten-into lst x)
          (cons x lst)))
    
    (define (flatten . lst)
      (reverse (reverse-flatten-into lst '())))
    

    使用的唯一外部函数是:conscarcdrnull?pair?

    这个函数的主要见解是fold 是一个非常强大的操作,应该是任何 Schemer 工具包的一部分。而且,如上面的代码所示,从第一原理构建起来非常简单!

    【讨论】:

    • 谢谢,这正是我想要的。
    • 谢谢!最好使用 list? 而不是 pair? 虽然(可以很容易地用 lambda 实现)来处理要展平的输入列表为空的情况(感谢 #guile 上的 chrislck 将我都指向这个例子和这个小错误)
    【解决方案2】:

    我不熟悉 Little Schemer 原语,因此您可能需要调整它以适应它。

    我不确定这是否是您想要的答案,但您可以使用原语编写 append

    (define (append l1 l2)
      (cond
        ((null? l1) l2)
        (else (cons (car l1) (append (cdr l1) l2)))))
    

    flatten 函数可以这样写。

    不确定这是否超出规则:)

    【讨论】:

      【解决方案3】:

      这是一个尝试。它使用 cons 并避免追加,因为它只会切掉它可以到达的第一个非对,并将其限制为它已经建立的新尾巴的扁平化。有时它会重写列表,然后再次调用 flatten。 Def不是最有效的方法。

      固定代码:

      (define (flatten x)
        (cond 
          ((null? x) x)
          ((and (pair? x) 
                (not (pair? (car x))))
           (cond 
             ((null? (car x)) (flatten (cdr x)))
             (else (cons (car x) (flatten (cdr x))))))
          ((and (pair? x)
                (pair? (car x)))
           (flatten (cons (caar x) 
                          (cons (cdar x) (cdr x)))))
          (else (cons x '()))))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-14
        • 2012-05-16
        • 1970-01-01
        • 2010-12-30
        • 2012-09-06
        • 2014-06-28
        • 2014-08-28
        • 2011-10-23
        相关资源
        最近更新 更多