Lisp通过列表列表使用成员

时间:2018-01-11 17:18:07

标签: lisp member

在常见的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?)之后事情变得非常复杂。请帮助!

1 个答案:

答案 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-notlambda

(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))
相关问题