在常见的lisp中我有一个符号树,如:
(setf a '((shoe (walks(town)) (has-laces(snow)))
(tree (grows(bob)) (is-green(house)) (is tall(work)))))
都是符号。
我想返回包含我搜索的符号的子列表(在这种情况下,我可能会使用符号shoe
进行搜索并返回包含它们的整个子列表。关键字始终位于第二层永远不会更深入
尝试使用:
(mapcar #'member (shoe my-list))
但要求shoe
成为一个列表(因为mapcar
?)之后事情变得非常复杂。请帮助!
答案 0 :(得分:0)
给出:
(setf a '((shoe (walks(town)) (has-laces(snow)))
(tree (grows(bob)) (is-green(house)) (is tall(work)))))
我们可以找到第一个(shoe ...)
子列表,如下所示:
(find 'shoe a :key #'car)
-> (SHOE (WALKS (TOWN)) (HAS-LACES (SNOW)))
即在对象列表(即列表)中进行搜索,并使用其car
作为搜索关键字。
如果可能存在重复项,并且我们想要一个以shoe
开头的所有子列表的列表,则Common Lisp的标准库会显得有些笨拙。没有一个很好的函数可以找到一个项目的所有实例;我们求助于remove-if-not
和lambda
:
(remove-if-not (lambda (x) (eq x 'shoe)) a :key #'car)
我们还可以编写一个loop
表达式:
(loop for (sym . rest) in a and
for whole in a
if (eq sym 'shoe) collect whole)
我们还可以使自己变得快速而肮脏的find-all
,可以像all
那样调用它:
(defun find-all (item sequence &key (key #'identity) (test #'eql))
(remove-if-not (lambda (elem) (funcall test item elem)) sequence :key key))
然后:
(find-all 'shoe a :key #'car)
--> ((SHOE (WALKS (TOWN)) (HAS-LACES (SNOW))))
(find-all 'x '((x 1) (y 2) (x 3) (z 4)) :key #'car)
--> ((X 1) (X 3))
(find 'x '((x 1) (y 2) (x 3) (z 4)) :key #'car)
--> ((X 1))