2011-01-29 25 views
5

Tôi muốn làm:Mapcar và assoc

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

và có nó trở

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

Mà dường như khá hợp lý, xem xét (assoc 'a '((a . b) (c . d) (s . f))) lợi nhuận (A . B)(assoc 's '((a . b) (c . d) (s . f))) lợi nhuận (S . F). Nhưng nó không hoạt động:

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

Bạn nghĩ gì?

Trả lời

7

Khi được sử dụng với hai danh sách, mapcar áp dụng chức năng ghép đôi cho các danh sách (và với ba danh sách, nó áp dụng cho chúng ba lần, v.v.). Vì vậy,

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

cũng giống như

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

(khi được sử dụng với danh sách có độ dài khác nhau, mapcar sử dụng kích thước của danh sách nhỏ nhất). Để có được những gì bạn muốn, bạn nên làm:

(mapcar (lambda (x) (assoc x '((a . b) (c . d) (s . f)))) '(a s)) 
5

Chúng tôi cần một cấp danh sách khác. Đối số thứ hai phải là danh sách các danh sách assoc.

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

((A . B)) 

Nhưng đối số thứ hai chỉ dài một phần tử. Bây giờ chúng ta có thể sử dụng một thủ thuật và biến nó thành một danh sách tròn:

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

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

Nếu chúng ta xây dựng một danh sách vòng tròn cho đối số thứ hai, thì nó hoạt động.

Là một chức năng:

(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

Nice. Tôi thực sự thích điều đó. – rhombidodecahedron

Các vấn đề liên quan