如何使用递归删除球拍列表中的第一个和最后一个元素

时间:2019-07-02 05:28:06

标签: list recursion racket

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

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

(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"))

4 个答案:

答案 0 :(得分: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)))])))

对于那些不熟悉球拍,Scheme或相关的Lisp的人,let中的命名为rid3的一开始可能比较神秘,因为它实际上一次执行的是两三件事。您可以找到the docs for it here。但是不要被愚弄了,它的工作原理与rid2相同。之所以命名为let正是因为这种模式如此普遍。

答案 1 :(得分:1)

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

(define (rid L)
  (rest (drop-right L 1)))

(rid '(1 2 3 4 5 6))
=> '(2 3 4 5)

答案 2 :(得分:0)

(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)))

答案 3 :(得分:0)

尾调用递归版本

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

具有基本的口吻(不是最有效的)

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