2011-01-29 81 views
5

我想這樣做:Mapcar和assoc命令

(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 

有什麼想法?

回答

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)) 
5

我們需要另一個列表級別。第二個參數應該是assoc列表的列表。

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)) 
+0

尼斯。我真的很喜歡那樣。 – rhombidodecahedron 2011-01-30 05:12:54