我有一个问题,如何返回没有给定列表的第n个元素的列表?例如,给定列表:(1 2 3 2 4 6)
,给定n = 4
,在这种情况下,返回列表应为(1 2 3 4 6)
。
答案 0 :(得分:8)
一个简单的递归解决方案:
(defun remove-nth (n list)
(declare
(type (integer 0) n)
(type list list))
(if (or (zerop n) (null list))
(cdr list)
(cons (car list) (remove-nth (1- n) (cdr list)))))
这将共享公共尾部,除非列表中包含n
个或更多元素,在这种情况下,它将返回一个新列表,其中包含与提供的元素相同的元素。
答案 1 :(得分:7)
使用remove-if
:
(defun foo (n list)
(remove-if (constantly t) list :start (1- n) :count 1))
butlast
/ nthcdr
解决方案(已更正):
(defun foo (n list)
(append (butlast list (1+ (- (length list) n))) (nthcdr n list)))
或者,可能更具可读性:
(defun foo (n list)
(append (subseq list 0 (1- n)) (nthcdr n list)))
使用loop
:
(defun foo (n list)
(loop for elt in list
for i from 1
unless (= i n) collect elt))
答案 2 :(得分:2)
这是一个有趣的方法。它用新符号替换列表的第n个元素,然后从列表中删除该符号。我没有考虑过它的效率如何(in)!
(defun remove-nth (n list)
(remove (setf (nth n list) (gensym)) list))
答案 3 :(得分:1)
稍微更通用的功能:
(defun remove-by-position (pred lst)
(labels ((walk-list (pred lst idx)
(if (null lst)
lst
(if (funcall pred idx)
(walk-list pred (cdr lst) (1+ idx))
(cons (car lst) (walk-list pred (cdr lst) (1+ idx)))))))
(walk-list pred lst 1)))
我们用它来实现所需的remove-nth:
(defun remove-nth (n list)
(remove-by-position (lambda (i) (= i n)) list))
并且调用:
(remove-nth 4 '(1 2 3 2 4 6))
编辑:塞缪尔评论的应用评论。
答案 4 :(得分:1)
对于你那里的所有haskellers,没有必要扭曲你的大脑:)
(defun take (n l)
(subseq l 0 (min n (length l))))
(defun drop (n l)
(subseq l n))
(defun remove-nth (n l)
(append (take (- n 1) l)
(drop n l)))
答案 5 :(得分:0)
我可怕的elisp解决方案:
(defun without-nth (list n)
(defun accum-if (list accum n)
(if (not list)
accum
(accum-if (cdr list) (if (eq n 0) accum (cons (car list) accum))
(- n 1))))
(reverse (accum-if list '() n)))
(without-nth '(1 2 3) 1)
应该可以轻松移植到Common Lisp。
答案 6 :(得分:0)
更简单的解决方案如下:
(defun remove-nth (n lst)
(append (subseq lst 0 (- n 1)) (subseq lst n (length lst)))
)
答案 7 :(得分:0)
破坏性版本,原始列表将被修改(除非n <1),
(defun remove-nth (n lst)
(if (< n 1) (cdr lst)
(let* ((p (nthcdr (1- n) lst))
(right (cddr p)))
(when (consp p)
(setcdr p nil))
(nconc lst right))))
这是elisp,但我认为这些是标准的lispy函数。
答案 8 :(得分:0)
(loop :for i :in '(1 2 3 2 4 6) ; the list
:for idx :from 0
:unless (= 3 idx) :collect i) ; except idx=3
;; => (1 2 3 4 6)
循环宏在Lisp编译器和宏扩展器生成的代码方面非常有用和有效。
运行测试并在代码段上方应用宏展开。