如何将列表转换为LISP中的集合?

时间:2015-11-30 15:27:30

标签: list set lisp common-lisp

我一直在尝试将线性列表转换为集合,但无济于事。每次我运行这个,我得到一些奇怪的编译错误,如“形成严重的lambda”,这指向我使用append的方式。这是我的代码:

(defun mem(e l)
  (cond
      ((null l) nil)
      ((equal e (car l)) t)
      ((listp (car l)) (mem e (car l)))
      (t(mem e (cdr l)))
  )
)

(defun st(l k)
  (cond
      ((null l) nil)
      (( mem '(car l) 'k) (st (cdr l) k))
      ((listp (car l)) (st (car l) k))
      ( t (st (cdr l) (append((car l) k)) ))
      (t(mem e (cdr l)))
  )
)

编辑:坦率地说,我只想删除列表中的重复项

2 个答案:

答案 0 :(得分:4)

首选标准库函数

  

编辑:坦率地说,我只想删除列表中的重复项

Common Lisp具有remove-duplicates功能。文档包括示例:

  

示例:

(remove-duplicates "aBcDAbCd" :test #'char-equal :from-end t) =>  "aBcD"
(remove-duplicates '(a b c b d d e)) =>  (A C B D E)
(remove-duplicates '(a b c b d d e) :from-end t) =>  (A B C D E)
(remove-duplicates '((foo #\a) (bar #\%) (baz #\A))
    :test #'char-equal :key #'cadr) =>  ((BAR #\%) (BAZ #\A))
(remove-duplicates '((foo #\a) (bar #\%) (baz #\A)) 
    :test #'char-equal :key #'cadr :from-end t) =>  ((FOO #\a) (BAR #\%))

您是否也试图压扁列表?

mem 的代码中执行以下操作:

  ((listp (car l)) (mem e (car l)))

看起来您希望您的成员函数也可以递归到子列表中。这有点值得怀疑,即使在使用集合时也是如此,因为集合传统上可以包含其他集合。例如,{{3},{4},5}是包含5,集合{3}和集合{4}的集合。 与集合{3,4,5}相同。您的 st 功能看起来也在尝试递归到列表中,这使得您似乎也想要展平列表。同样,这有点值得怀疑,但是如果你想这样做,那么转换到集合会更容易,因为“扁平化,然后删除重复”过程:

(defun flatten (list)
  "Returns a fresh list containing the leaf elements of LIST."
  (if (listp list)
      (mapcan 'flatten list)
      (list list)))

;; CL-USER> (flatten '(1 2 (3 4) 5 ((6))))
;; (1 2 3 4 5 6)

(defun to-set (list)
  "Returns a set based on the elements of LIST.  The result
is a flat list containing the leaf elements of LIST, but
with any duplicate elements removed."
  (delete-duplicates (flatten list)))

;; CL-USER> (to-set '(1 3 (3 4) ((4) 5)))
;; (1 3 4 5)

备注

  

我得到了一些奇怪的编译错误,例如“形成错误的lambda”,它指向我使用追加的方式。

是的,您尝试将追加称为:(追加((车l)k))。这实际上不是追加的问题。请记住,Lisp中函数调用的语法是(函数参数...)。这意味着你有:

(append      ((car l) k))
 <function>  <argument1>

但你的 argument1 也是一个函数调用:

((car l)     k          )
 <function>  <argument1>

在Common Lisp中,您不能将(car l)用作函数。 函数唯一可以出现的是符号(例如,汽车追加)或lambda表达式(例如 (lambda(x)(+ x 1))。

您想要调用(追加(车辆l)k)

答案 1 :(得分:2)

首先,CL没有set数据类型。 Lists, however, can be used as sets,您不需要为此编写任何特殊代码。

其次,我不明白你的st函数应该做什么,但我敢打赌,在第二个cond子句中你应该引用{{1 }和(car l)。您应该为函数使用有意义的名称并避免使用缩写。根据您在评论中的说明,您应该使用pushnew代替。

第三,你的k函数非常奇怪,我很确定你不是指你写的内容:mem沿着树中的路径搜索 {{ 1}},而不是列表 e。根据您在评论中的说明,您应该检查 ll

car