从Lisp列表中删除一个元素。

3
我正在为计算机科学课程的作业工作, 但遇到了一些问题。我知道社区反对提供明确的家庭作业答案,这也不是我的目的; 我想要被放在正确的轨道上或思考过程中。我将尽可能多地提供信息,以便让您了解我正在处理什么以及我如何受阻。
首先,这是LISP语言非常快速的“介绍”。该课程会引导我们通过几种不同类型的编程语言,帮助我们了解编程的不同方面以及它们发展的历史。因此,项目规则如下:
  • 不能使用任何循环功能; 必须使用递归
  • 只能使用以下固有函数 setq, cons, append, list, equal, defun, car, cdr, 和 cond
  • 可以创建“辅助函数”,可以用于在函数的条件中创建额外的步骤(类似于嵌套条件)
我遇到的问题是,我应该创建一个接受列表作为参数的函数,扫描该列表以查找重复项,并删除重复项,然后返回列表。所以,如果我传递了一个列表 '(a b c b a d e a),它将返回(a b c d e)。
到目前为止,我认为最好创建一个名为list_member的函数,将元素与列表进行比较,并且如果该元素在列表中,则返回T,如果不在列表中,则返回nil。
(defun list_member (x L)
  (cond ((null L) nil)             ;if list L is empty, return NIL
    ((equal x (car L)) T)          ;if element x is in L, return T
    (T (list_member x (cdr L)))))  ;else, recursively check remainder of L

我希望您能将其用于函数 rem_dup 中,如下所示:

(defun rem_dup (L)
   (cond ((null L) nil)                     ;if list L is empty, return NIL to user
     (( list_member (car L) cdr L )) (...)  ;part I am having trouble with
     (T (rem_dup (cdr L)))))                ;else, check rest of list recursively

我的问题是,我似乎无法通过可用的函数来去除重复项并组合列表。实际上,当list_member返回true时,我不知道该从何处开始做什么。唯一保留列表格式的函数是APPEND,因为我正在处理单个元素(在这种情况下,即使嵌套列表也被视为一个元素)。我可以使用的所有列表连接函数(APPEND、CONS、LIST)都是非破坏性的。
我想出了很多解决方案,但返回的列表与我想要的完全不同。我认为在此列出它们可能会造成混淆。我已经遇到了自己无法回答正确问题的障碍,所以我想向大家提出一个问题,看看他们是否能想出我还没有想到的问题。
感谢您的见解。

你能创建列表的副本,还是必须要修剪过的列表本身? - Floris
请花几分钟时间学习如何格式化Lisp代码 - danlei
感谢提供格式化链接!我一直按照老师教我们的方式缩进...也许我会把这个链接发给他看看。 - brandont
不用谢。是的,你的教授绝对不应该向他的学生教授这种缩进风格。 - danlei
1个回答

5
你的案例顺序是错误的。如果第一个元素存在于列表的其余部分中,则它是一个重复项,因此您想要省略它。否则,您希望返回一个包含第一个元素接在剩余部分的rem_dup前面的列表。
(defun rem_dup (L)
   (cond ((null L) nil)                         ; if list L is empty, return NIL to user
         ((list_member (car L) (cdr L )) (rem_dup (cdr L))) ; Skip duplicate element
         (T (cons (car L) (rem_dup (cdr L)))))) ; else include it, and check rest of list recursively

非常感谢您的解释。在项目中,我还有几个涉及类似过程的函数。这应该有助于弄清楚它们! - brandont

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接