Scheme 删除列表(方案)的最后一个元素

Scheme 删除列表(方案)的最后一个元素,scheme,racket,Scheme,Racket,所以我必须删除scheme中列表的最后一个元素 例如,假设我有一个列表(1234)。我需要返回: (1 2 3) 我的想法是: reverse(list) car(list) reverse(list) scheme(racket)中是否有reverse函数?如果元素不是最后一个,我将执行一个递归函数,它沿着列表向下并附加元素(使用cons),如果元素不是最后一个,则不附加任何内容 我已经好几年没做这个计划了,所以这是我能做的 有人可以运行如何实现它(除非它是家庭作业,否则他们可能不应该!)

所以我必须删除scheme中列表的最后一个元素

例如,假设我有一个列表
(1234)
。我需要返回:

(1 2 3)
我的想法是:

reverse(list)
car(list)
reverse(list)

scheme(racket)中是否有
reverse
函数?

如果元素不是最后一个,我将执行一个递归函数,它沿着列表向下并附加元素(使用
cons
),如果元素不是最后一个,则不附加任何内容

我已经好几年没做这个计划了,所以这是我能做的

有人可以运行如何实现它(除非它是家庭作业,否则他们可能不应该!)

您写道:“倒车,倒车,倒车”。我相信你的意思是写“反向,cdr,反向”。这个解决方案没有错;列表的大小是线性的,就像任何使用标准列表的解决方案一样

作为代码:

;; all-but-last: return the list, not including the last element
;; list? -> list?
(define (all-but-last l) (reverse (cdr (reverse l))))
如果列表的多次遍历或另一个列表副本的不必要的构造让您感到困扰,您当然可以通过直接编写来避免它

考虑到你的解决方案,我假设这不是家庭作业

下面是它在球拍中的样子:

#lang racket

(require rackunit)

;; all-but-last : return the list, except for the last element
;; non-empty-list? -> list?
(define (all-but-last l)
  (cond [(empty? l) (error 'all-but-last "empty list")]
        [(empty? (rest l)) empty]
        [else (cons (first l) (all-but-last (rest l)))]))

(check-equal? (all-but-last '(3 4 5))
              '(3 4))
(使用
(需要srfi/1)
)在球拍中激活)具有
右降功能:

 (drop-right '(1 2 3 4) 1)   ; => (1 2 3)

有一个
反向
,但使用它效率不高。我建议使用以下递归函数

(define (remove-last lst)
    (if (null? (cdr lst))
        '()
        (cons (car lst) (remove-last (cdr lst)))))

(remove-last '(1 2 3 4)) ; returns '(1 2 3)

if
检查它是否位于列表的最后一个元素。

我将编写一个简单的递归,将典型的“empty?mylist”基本情况更改为“empty”(rest mylist),”以便在输入列表只有1个元素时返回空

(define (removelast mylist)
  (cond
    [(empty? (rest mylist)) empty]
    [(cons? mylist) (cons (first mylist) (removelast (rest mylist)))]))

(removelast (list 1 2 3 4 5))

顺便说一句,这个代码在Racket/PLT Scheme中,它是Scheme的一个子集。

我做了一些比以下更简单的事情:reverse(list)、car(list)、reverse(list)要获取最后一个元素,请检查:

(define (last-one liste)
  (if(null? (cdr liste))
     null
     (cons (car liste) (last-one (cdr liste)))
  )
)

p、 s:这个解决方案使用了几个racket ISM:first&rest、error、check equal?等。我假设这是可以的,因为您的问题被标记为“racket”。-1每次添加一个列表都是一个O(n)操作,这使得您的整个函数都是O(n²)。这是处理链表时得到的结果。在中附加到列表不是O(n)。附加到数组支持列表的是O(n)。附加到链表(就像在scheme中一样)的是O(1)。@glowcoder:不是真的。链表的前缀是O(1)。附加到链表的是要附加的列表上的O(n)。(记住,方案列表是单链接列表,而不是双链接列表。)@Chris不,不是。当你遍历列表时,你已经有了对列表中最后一个元素的引用(尾部递归的美妙之处),所以你知道它不是O(n),而是O(1)。你在解释我对append这个词的使用,是指实际的append函数,而不是纯文本的append概念。在这种情况下,我承认append函数会导致函数的顺序膨胀实际上,
reverse
是O(n),就像函数一样。这两种方法都可以。@Chris:它们确实具有相同的复杂度,但该算法的速度应该仍然是原来的两倍,因为它只遍历列表一次。只有在使用非常狭窄的“遍历”定义的情况下。由于您的函数不是尾部递归函数,因此从调用堆栈中考虑可能会被视为第二次遍历。@ChrisJester Young,我不知道Racket是否实现尾部递归模cons,但这在这里就行了。他可能需要为赋值执行此操作。:)我希望我能在我的作业中使用它;)基于这个答案,我相信core Racket现在已经具备了这个功能,因此不再需要
require
了。事实上,StackOverflow最好的一点是,一旦发布了一个问题,它就可以在其他帖子中引用和构建。因此,当你搜索东西时,这是谷歌最热门的搜索之一,因此,如果有人在将来遇到这一点,他们可以从这里学到东西。:)要了解Racket是否具有反转功能,请使用docs.Racket-lang.org进行查找。(反转(cdr(reverse)(1 2 3)))在chez和Racket中工作正常。在任何情况下,如果你打开解释器(如终端),键入一个字母,后跟一个标签,你应该访问自动完成建议,这是一个很好的方式来回答这个问题自己。