【问题标题】:Mapcar and assoc地图车和副驾驶
【发布时间】:2011-06-17 22:21:30
【问题描述】:
我想做:
(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
有什么想法吗?
【问题讨论】:
标签:
lisp
common-lisp
clisp
【解决方案1】:
当与两个列表一起使用时,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))
【解决方案2】:
我们需要另一个列表级别。第二个参数应该是关联列表的列表。
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))