[英]How do I remove the first and last element in a list in Racket using recursion
Essentially I am trying to remove the first and last element in a list.本质上,我试图删除列表中的第一个和最后一个元素。 I have currently been able to determine how to remove the last element in the list but i'm struggling how to remove the first element in the list with the last element in the list.
我目前已经能够确定如何删除列表中的最后一个元素,但我正在努力如何删除列表中的第一个元素和列表中的最后一个元素。
Here is the code I have so far.这是我到目前为止的代码。 Is there a way I can modify my code so I am able to include removing the first element in the list.
有没有办法可以修改我的代码,以便我能够删除列表中的第一个元素。
(define (rid L)
(cond
[(empty? L) '()]
[(empty? (rest L)) '()]
[(cons (first L) (rid (rest L)))]))
Here is the results I am expecting with my code这是我的代码期望的结果
(check-expect (rid (list 1 2 3 4 5)) (list 2 3 4))
(check-expect (rid (list "cat" "dog" "giraffe")) (list "dog"))
With many recursive algorithms, it is not uncommon to actually implement them with two procedures: one to set up the initial conditions and a second one to do the actual recursion, like so:对于许多递归算法,实际使用两个过程来实现它们并不少见:一个用于设置初始条件,第二个用于执行实际递归,如下所示:
(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))
With (define r (if (empty? L) '() (rest L)))
we strip off the first element of the list;使用
(define r (if (empty? L) '() (rest L)))
我们去掉列表的第一个元素; no recursion is actually necessary for this step.这一步实际上不需要递归。 Then we define the same procedure you had before with a different name and call it with our new list that already has the first element stripped off.
然后,我们用不同的名称定义与之前相同的过程,并使用我们的新列表调用它,该列表已经去除了第一个元素。 If you want the first element stripped off, just strip off the first element;
如果你想去掉第一个元素,就去掉第一个元素; don't overthink it :) .
不要想太多:)。
In a language like Racket that allows closures and nested procedures, you don't actually even need to define both procedures at the top "global" module scope;在像 Racket 这样允许闭包和嵌套过程的语言中,您实际上甚至不需要在顶部“全局”模块范围内定义这两个过程; just define your recursive procedure inside your initial procedure and call it from there.
只需在初始过程中定义递归过程并从那里调用它。 Example:
例子:
(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))
Another, somewhat cleaner, way to do the above is to use a named let
, which allows us to simultaneously set up our initial conditions, create a named procedure, and then call that procedure immediately from within itself.另一种更简洁的方法是使用命名的
let
,它允许我们同时设置初始条件,创建命名过程,然后立即从其内部调用该过程。 We do that like so:我们这样做:
(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)))])))
To those unfamiliar with Racket, Scheme, or a related Lisp, the named let
in rid3
may be more cryptic at first since it is really doing two or three things at once.对于那些不熟悉 Racket、Scheme 或相关 Lisp 的人来说,
rid3
的命名let
一rid3
可能更神秘,因为它实际上同时做两三件事。 You can find the docs for it here .你可以在这里找到它的文档。 Don't be fooled though, it works exactly the same as
rid2
.不过不要被愚弄,它的工作原理与
rid2
。 Named let
exists precisely because this pattern is so common.命名
let
存在正是因为这种模式非常普遍。
Just for fun - In Racket you can solve this problem without using explicit recursion.只是为了好玩 - 在 Racket 中,您可以在不使用显式递归的情况下解决这个问题。 Always try to use existing procedures to solve your problems:
始终尝试使用现有程序来解决您的问题:
(define (rid L)
(rest (drop-right L 1)))
(rid '(1 2 3 4 5 6))
=> '(2 3 4 5)
(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)))
tail call recursive version尾调用递归版本
(define (rid lst (acc '()))
(cond ((empty? lst) acc)
((empty? (cdr lst)) (cdr (reverse acc)))
(else (rid (cdr lst) (cons (car lst) acc)))))
with elementar lisp (not the most efficient)使用 elementar lisp(不是最有效的)
(define (rid1 lst)
(cdr (reverse (cdr (reverse lst))))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.