5

我想要做:

(mapcar #'assoc '(a s) '((a . b) (c . d) (s . f)))

并让它返回

((A . B) (S . F))

(assoc 'a '((a . b) (c . d) (s . f)))考虑到回报(A . B)(assoc 's '((a . b) (c . d) (s . f)))回报,这似乎很合理(S . F)。但可惜它不起作用:

*** - ASSOC: A is not a list
The following restarts are available:
ABORT          :R1      Abort main loop

有什么想法吗?

4

2 回答 2

7

当与两个列表一起使用时,mapcar将函数成对地应用于列表(对于三个列表,它将它们三重应用等)。所以

(mapcar #'assoc '(a s) '((a . b) (c . d) (s . f)))

是相同的

( (assoc 'a (a . b)) (assoc 's (c . d)) )

(当与不同长度的列表一起使用时,mapcar使用最小列表的大小)。为了得到你想要的,你应该这样做:

(mapcar (lambda (x) (assoc x '((a . b) (c . d) (s . f)))) '(a s))
于 2011-01-29T23:46:21.850 回答
5

我们需要另一个列表级别。第二个参数应该是关联列表的列表。

CL-USER >  (mapcar #'assoc '(a s) '(((a . b) (c . d) (s . f))))

((A . B))

但是第二个参数只有一个元素长。现在我们可以使用一个技巧,让它成为一个循环列表:

CL-USER > (mapcar #'assoc '(a s) '#1=(((A . B) (C . D) (S . F)) . #1#))

((A . B) (S . F))

如果我们为第二个参数构造一个循环列表,那么它就可以工作。

作为一个函数:

(defun circular (list)
  (if (null list)
      list
    (setf (cdr (last list)) list)))

CL-USER > (mapcar #'assoc '(a s) (circular '(((a . b) (c . d) (s . f)))))

((A . B) (S . F))
于 2011-01-30T02:42:34.290 回答