我想从list 'b中过滤掉list 'a‘的所有元素,并返回过滤后的'b’。这是我的函数:
(defun filter (a b)
"Filters out all items in a from b"
(if (= 0 (length a)) b
(filter (remove (first a) a) (remove (first a) b))))
我是lisp的新手,不知道'remove‘是怎么做的,这个过滤器会在什么时候运行?
发布于 2010-07-27 15:33:27
有两种方法可以找到答案:
让我们看一下源代码。
(使用ENDP instead.)
(不是在a
__上使用REMOVE,而是与其余部分一起递归。)
(当为applicable.)时,使用循环结构,如DO、DOLIST、DOTIMES、LOOP、REDUCE、MAPC、MAPL、MAPCAR、MAPLIST、MAPCAN或MAPCON,而不是递归
摘要:这是非常幼稚的代码,性能很差。
Common Lisp提供了这样的内置功能: SET-DIFFERENCE应该做你想做的事情。
http://www.lispworks.com/documentation/HyperSpec/Body/f_set_di.htm#set-difference
发布于 2010-07-27 15:05:52
Common Lisp不支持tail-call optimization (根据标准),您可能会因为一个糟糕的调用堆栈(取决于实现)而耗尽内存。
发布于 2010-07-30 03:11:21
我不会写这个函数,因为作为Rainer Joswig says,标准已经提供了SET-DIFFERENCE
。尽管如此,如果我必须提供该函数的实现,我会使用以下方法:
(defun filter (a b)
(let ((table (make-hash-table)))
(map 'nil (lambda (e) (setf (gethash e table) t)) a)
(remove-if (lambda (e) (gethash e table)) b)))
这样做有几个优点,最重要的一个是它只遍历b
一次;如果a
很长,使用哈希表来跟踪a
中的元素可能会执行得更好。
此外,使用像MAP
和REMOVE-IF
这样的通用序列函数意味着该函数可以与字符串和向量以及列表一起使用,这比标准的SET-DIFFERENCE
函数更有优势。这种方法的主要缺点是如果您希望使用:TEST
参数扩展函数,该参数允许用户提供默认EQL
以外的相等谓词,因为CL哈希表只使用少量预定义的相等谓词(准确地说是EQ
、EQL
、EQUAL
和EQUALP
)。
https://stackoverflow.com/questions/3340837
复制相似问题