公共LISP函数,用于删除列表中每个子列表的第n个位置的元素

时间:2015-04-18 19:17:33

标签: list common-lisp

我现在已经乱搞了常见的LISP几周了,大多数都试图练习递归。我想做的是有一个功能

(defun rem (n l) 
   ; code here
)

其中n 总是非负整数,l可以是atom / list / null。该函数删除了第n个元素(基于一个索引):

  • 列表(l)本身

  • 原始列表包含的任何级别子列表

我认为使用删除 nth 会让这项任务变得轻而易举,但我还没有取得任何成功。

任何答案/实际代码将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:1)

您没有说出是否需要remove功能或delete功能。我会在这里做非破坏性的版本。

您可以通过在索引之前创建所有元素的新列表来为一个列表创建remove-nth,然后使用要删除的cons的尾部来共享尽可能多的结构。以下是使用subseqnconcnthcdr的实现,以显示没有递归的情况。

(defun remove-nth (n list)
  (nconc (subseq list 0 n) (nthcdr (1+ n) list)))

(defparameter *test* (list 0 1 2 3 4 5 6))
(remove-nth 3 *test*) ; ==> (0 1 2 4 5 6)
(remove-nth 0 *test*) ; ==> (1 2 3 4 5 6)

递归函数看起来像这样:

(defun remove-nth-rec (n list)
  (assert (not (null list)))
  (if (zerop <??>)
      <??>
      (cons <??> (remove-nth-rec <??> <??>))))

你也可以递归地在每个子列表上创建这个功能。我用mapcar

执行此操作
(defun remove-all-nth (n lol)
  (mapcar (lambda (x) (remove-nth n x)) lol))

(remove-all-nth 0 '((a b c) (0 1 2) (I II III))) ; ==> ((b c) (1 2) (II III))

递归函数看起来像这样:

(defun remove-all-nth-rec (n list)
  (if (null <??>)
      nil
      (cons (remove-nth-rec n <??>)
            (remove-all-nth-rec n <??>))))