【问题标题】:How to move the first element of a list to the end of the list using Scheme?如何使用 Scheme 将列表的第一个元素移动到列表的末尾?
【发布时间】:2012-10-06 02:23:49
【问题描述】:

我一直在研究这个,我可以在列表的末尾添加“一些东西”,但我遇到的问题是将列表的第一个元素添加到同一个列表的末尾.

例如:

{1, 2, 3, 4} 变为 {1, 2, 3, 4, 1}。

这是我遇到问题的代码:

(define (copy-first-to-end lst)
  (cond [(empty? lst)   
         (cons (first lst) empty)]       
        [else  (cons (first lst)    
               (copy-first-to-end (rest lst)))])) 

这段代码的问题是,对于空的?条件,答案调用 (first lst) 但因为它是递归的,所以这个列表的第一个元素是空的。由于方案是动态类型的,所以我不能将第一个元素存储在任何地方(至少我认为我不能)。

我怎样才能让它工作,只使用基本的列表功能? (例如,cons、cons?、empty? first、last、rest)

【问题讨论】:

    标签: list recursion scheme append


    【解决方案1】:

    你可以使用闭包来存储你想要的任何东西。

    这是我写的解决方案,删除了一些细节,给你一些思考的空间。 :-)

    (define (copy-first-to-end lst)
      (define top ???)
      (define (inner lst)
        (if (null? lst) ???
            (cons ??? (inner ???))))
      (inner ???))
    

    在这种情况下,inner 是一个闭包,除其他外,它可以访问 top 变量(您将使用它来存储您感兴趣的值)。

    【讨论】:

    • 也许不是,但请注意,您在解决方案中每次运行 append-to-end 之间传递的 a 不变。在这种情况下,我会说使用闭包确实更干净。
    • 考虑一下,由于对 append-to-end 的调用处于尾部位置,因此我的解决方案根本没有做任何额外的工作。哪个更清洁还有待商榷。
    • 是的,这是我自己经常进行的辩论。对于 SO 上的代码 sn-ps,我倾向于喜欢非封闭形式,因为它的代码行数更少。但是对于我自己的代码,我更喜欢闭包形式,因为内部函数更短。
    【解决方案2】:

    因此,您实际上是在尝试编写自己的 append 函数实现,在特殊情况下,您将附加一个包含列表中第一个 s 表达式的列表。您的问题是您不能将平面列表转换为平面列表并因此获得单个平面列表。使用 cons 执行此操作的唯一方法是将第一个列表分解为其组成的 s 表达式,然后将它们 以相反的顺序 合并到第二个列表中。递归应该使这成为一项简单的任务。

    (define (append-first-to-end lst)
      (define (append-to-end a lst)
        (if (null? (cdr lst)) ???
          (cons ??? (append-to-end a ???))))
      (append-to-end (car lst) lst))
    

    在我的例子、克里斯的例子和我的开头段落之间,你应该能够填空。

    我确实希望从 lst 获得最终 s 表达式后所需的操作是显而易见的......

    【讨论】:

    • 请记住,在递归的每个阶段,您都希望将单个 s 表达式转换为其他内容。
    • 非常有意义。出于某种原因,我试图在一个函数中完成它,但是有两个函数使它更容易。非常感谢。
    猜你喜欢
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 2023-03-17
    • 2017-07-10
    • 1970-01-01
    • 2011-06-22
    相关资源
    最近更新 更多