【问题标题】:How do I remove the first and last element in a list in Racket using recursion如何使用递归删除 Racket 列表中的第一个和最后一个元素
【发布时间】:2019-11-12 17:06:15
【问题描述】:

基本上,我正在尝试删除列表中的第一个和最后一个元素。我目前已经能够确定如何删除列表中的最后一个元素,但我正在努力如何使用列表中的最后一个元素删除列表中的第一个元素。

这是我到目前为止的代码。有没有办法可以修改我的代码,以便我能够删除列表中的第一个元素。

(define (rid L)
  (cond
    [(empty? L) '()]
    [(empty? (rest L)) '()]
    [(cons (first L) (rid (rest L)))]))

这是我的代码所期望的结果

(check-expect (rid (list 1 2 3 4 5)) (list 2 3 4))
(check-expect (rid (list "cat" "dog" "giraffe")) (list "dog"))

【问题讨论】:

    标签: list recursion racket


    【解决方案1】:

    对于许多递归算法,实际上用两个过程来实现它们并不少见:一个是设置初始条件,另一个是执行实际递归,如下所示:

    (define (rid-inner li)
      (cond
        [(empty? li) '()]
        [(empty? (rest li)) '()]
        [(cons (first li) (rid-inner (rest li)))]))
    
    (define (rid1 L)
      (define r (if (empty? L) '() (rest L)))
      (rid-inner r))
    

    使用(define r (if (empty? L) '() (rest L))),我们去掉了列表的第一个元素;这一步实际上不需要递归。然后我们用一个不同的名字定义你之前的过程,并用我们已经去掉第一个元素的新列表来调用它。如果要剥离第一个元素,只需剥离第一个元素;不要想太多:)。

    在像 Racket 这样允许闭包和嵌套过程的语言中,您实际上甚至不需要在顶级“全局”模块范围内定义这两个过程;只需在初始过程中定义递归过程并从那里调用它。示例:

    (define (rid2 L)
      (define r (if (empty? L) '() (rest L)))
      (define (rid-inner li)
        (cond
          [(empty? li) '()]
          [(empty? (rest li)) '()]
          [(cons (first li) (rid-inner (rest li)))]))
      (rid-inner r))
    

    完成上述操作的另一种更简洁的方法是使用命名let,它允许我们同时设置初始条件,创建命名过程,然后立即从其内部调用该过程。我们这样做:

    (define (rid3 L)
      (let rid-inner ([li (if (empty? L) '() (rest L))])
        (cond
          [(empty? li) '()]
          [(empty? (rest li)) '()]
          [(cons (first li) (rid-inner (rest li)))])))
    

    对于那些不熟悉 Racket、Scheme 或相关 Lisp 的人来说,rid3 中名为 let 的人一开始可能会更加神秘,因为它实际上是同时做两三件事。你可以找到the docs for it here。不过不要上当,它的工作原理与rid2 完全相同。命名let 的存在正是因为这种模式非常普遍。

    【讨论】:

      【解决方案2】:

      只是为了好玩 - 在 Racket 中,您无需使用显式递归即可解决此问题。始终尝试使用现有程序来解决您的问题:

      (define (rid L)
        (rest (drop-right L 1)))
      
      (rid '(1 2 3 4 5 6))
      => '(2 3 4 5)
      

      【讨论】:

        【解决方案3】:
        (define (rid L)
          (if (< (length L) 3)
              '()
              (reverse (rest (reverse (rest L))))))
        
        ;;; recursion inside and more general
        ;;; you can setting which position 0~n-1 you want to remove
        
        (define (rid-v2 L)
          (local ((define remove-index-list (list 0 (- (length L) 1)))
                  (define (auxf L k)
                    (cond
                      [(empty? L) '()]
                      [(memq k remove-index-list) (auxf (rest L) (+ k 1))]
                      [else (cons (first L)
                                  (auxf (rest L) (+ k 1)))])))
            (auxf L 0)))
        

        【讨论】:

          【解决方案4】:

          尾调用递归版本

          (define (rid lst (acc '()))
            (cond ((empty? lst) acc)
                  ((empty? (cdr lst)) (cdr (reverse acc)))
                  (else (rid (cdr lst) (cons (car lst) acc)))))
          

          使用基本的 lisp(不是最有效的)

          (define (rid1 lst)
            (cdr (reverse (cdr (reverse lst))))
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-08-15
            • 1970-01-01
            • 1970-01-01
            • 2021-07-12
            • 1970-01-01
            • 2020-09-06
            • 2016-08-09
            • 2011-06-06
            相关资源
            最近更新 更多