从Lisp中的列表中删除最后两个元素

时间:2017-07-21 05:27:03

标签: common-lisp

我需要从公共列表中的列表中删除最后两个元素,但我只能删除一个。有什么办法?

(defun my-butlast (list)
        (loop for l on list
              while (rest l)
              collect (first l)))

2 个答案:

答案 0 :(得分:4)

简单:反向,弹出,弹出,反向 ;-) 1

更有效率,以下也适用:

(let ((list '(a b c d)))
  (loop 
    for x in list
    for y in (cddr list)
    collect x))

对于某些任意的L和N,也可以这样写:

(mapcar #'values L (nthcdr N L)) 

它的工作原理是因为多个列表上的迭代受最短列表的限制。这里重要的是第二个列表的长度(我们不关心它的值),即当该值为正时,原始列表的长度减去N,否则为零。请注意,NTHCDR方便地使用大于参数中给出的列表长度的大小。在第二个例子中,我使用VALUES函数作为广义标识函数; MAPCAR仅使用计算值的主值,因此可以根据需要使用。 该行为与实际的BUTLAST 2 函数一致,该函数返回nil,其中N大于列表中元素的数量。实际的BUTLAST函数也可以处理不正确的(虚线)列表,但上面的版本不能。

1。 (alexandria:compose #'nreverse #'cddr #'reverse)

2。 BUTLAST被指定为等同于(ldiff list (last list n))。我完全忘记了LDIFF的存在!

答案 1 :(得分:3)

标准中有一项功能:butlast,或者如果您愿意修改输入列表, nbutlast

  

butlast返回列表的副本,其中省略了最后n个conses。如果未提供n,则其值为1.如果列表中的con少于n个,则返回nil,如果是nbutlast,则不修改list。

     

nbutlast就像butlast,但是nbutlast可以修改列表。它将cons n + 1的cdr从列表末尾更改为nil。

示例:

CL-USER> (butlast '(1 2 3 4 5) 2)
(1 2 3)
CL-USER> (nbutlast (list 6 7 8 9 10) 2)
(6 7 8)

你调用你的函数 my-butlast 的事实表明你可能知道这个函数,但你没有提到不想使用这个函数,所以我认为它仍然是公平的游戏。把它包装起来很容易:

CL-USER> (defun my-butlast (list)
           (butlast list 2))
MY-BUTLAST
CL-USER> (my-butlast (list 1 2 3 4))
(1 2)