我在LISP中有这个例子,它从列表的每个级别删除给定的数字:
(defun remove_aux (e l)
(cond
((equal e l) nil)
((atom l) (list l))
(t(list(apply 'append (mapcar #'(lambda (l) (remove_aux e l)) l))))))
(defun remove_el (e l)
(car (remove_aux e l)))
所以,如果它像这样运行:(remove_el 2 '(1 2 3 ((2 3 2) 4))) => (1 3 ((3) 4))
我不太清楚这条线是如何工作的:(t(列出(应用'追加(mapcar#'(lambda(l)(sterge_aux e l))l))))
如果我没有列表的行并添加((t(mapcar #'(lambda (l) (remove_aux e l)) l)))
,则结果为((1) NIL (3) ((NIL (3) NIL) (4))))
如果它已附加但不是列表( (t(apply 'append (mapcar #'(lambda (l) (remove_aux e l)) l))) )
,则结果为(1 3 3 4)
并且我不知道得到原因,因为我在Common Lisp控制台中做(apply 'append '((1) NIL (3) ((NIL (3) NIL) (4)))))
,结果是((1 3 (NIL (3) NIL) (4)))
所以我真的很困惑。有人可以一步一步向我解释这一切是如何运作的吗?
答案 0 :(得分:1)
我已经注释了下面的代码,我希望,解释发生了什么。你可能会感到困惑,因为我正在lambda中重新定义...所以t行(在你的例子中)上有2“l”,但第一个与第二个不同。
(defun remove_aux (e l)
(cond
((equal e l) nil) ;if e equals l return nil
((atom l) (list l)) ;if l is an atom return a list with just l in it
(t ; otherwise...
(list ;create a list
(apply 'append ; whose contents are created by appending
; together the lists that come out of this mapcar
; (apply the append method)
(mapcar #'(lambda (l) ( ; iterate over each of the elements in list l
; the one after the lambda not the one
; being passed to the lambda.
; (this is a horrible name choice
; lambda(l-item) would be much better)
remove_aux e l
; recursively call this method
; with e (which was passed in at the start)
; and l which isn't the l passed in,
; but is an entry of it (see why naming's
; so important?)
; this returns a list
; which will get appended by the append
; with the results of all the other calls
; to remove_aux for each item in the outer l
)
) l)
)))))
(defun remove_el (e l)
(car (remove_aux e l)
)
)
答案 1 :(得分:1)
;; append elements of each list in argument together
(append '(a) '(b) '(c d) '(e)) ; ==> (a b c d e)
;; append elements of each sublist in argument
(apply #'append '((a) (b) (c d) (e))) ; ==> (a b c d e)
;; apply function on each element of list into new list
(mapcar #'(lambda (x) (+ x 1)) '(1 3 5 6)) ; ==> (2 4 6 7)
那么默认情况在你的函数中做了什么..它适用于lst的每个子列表并将其包装在一个列表中,所以如果l
是'(a y 2 z)
并且e
是2
,然后mapcar
的结果是'((a) (y) () (z))
,这是apply-append
的参数,它将元素再次连接到一个列表中。连接列表时,要删除的元素是一个空列表,并且在连接过程中实际上被忽略了。
由于您在助手中创建了所有附加的列表,因此您可以将apply-append
替换为(mapcan #'(lambda (l) (remove_aux e l)) l)
。更明显的方法是使用reduce
,而更有效的方法可能会使用loop
。
答案 2 :(得分:0)
实现您想要实现的目标的过程基本上类似于以下过程:
(defun remove-all (e l)"Removes all occurrences of e from a list l."
(cond
((null l) '())
((equal e (car l)) (remove-all e (cdr l)))
((not (atom (car l)))
(cons (remove-all e (car l))
(remove-all e (cdr l))))
(t (cons (car l)
(remove-all e (cdr l))))))
;note: the e is not neccessarily an atom, the l is not necessarily a list of atoms.
你问题中的程序有不必要的碎片,如追加,地图等。
如果您在下面推荐,我会解释算法。
有一个很好的黑客。