简体   繁体   English

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

[英]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的命名letrid3可能更神秘,因为它实际上同时做两三件事。 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.

相关问题 在球拍中,如何使用递归求和列表中的交替值 - In Racket how do i sum the alternating values in a list using recursion 在使用递归的球拍中,如果列表“ L”的总和为n但L中的值没有重复,我如何返回#true - In Racket using recursion how do I return #true if a list “L” sums to n but no values in L are duplicated 在Racket中,如何使用struct而不是仅使用高阶函数或递归来查找列表的长度 - In Racket how do i find the length of a list using struct instead of just using only higher-order functions or recursion 如何删除列表中列表中的第一个元素? - How do I remove the first element in a list within a list? 在不破坏括号格式的情况下删除列表中的最后一个元素(括号) - Remove Last Element on List Without Ruining Bracket Formatting (Racket) 从Haskell中的列表中删除第一个和最后一个元素 - Remove the first and the last element from a list in Haskell 如何去掉以(.)分隔的首尾元素的首尾值,需要加入列表中的其他元素 - How to remove the first and last value of the first and last element that is separated by (.) and need to join the other elements in the list 如何使用forEach删除列表中的元素? - How do I remove an element in a list, using forEach? 如何获取列表的最后一个元素? - How do I get the last element of a list? 消除球拍列表中最后一次出现的元素 - eliminate the last occurrence of an element in a list in racket
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM