我需要从公共列表中的列表中删除最后两个元素,但我只能删除一个。有什么办法?
(defun my-butlast (list)
(loop for l on list
while (rest l)
collect (first l)))
答案 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)