Вопрос

Я хотел бы сделать:

(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

Какие-нибудь мысли?

Это было полезно?

Решение

При использовании с двумя списками, 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))

Другие советы

Нам нужен другой уровень списка. Второй аргумент должен быть списком списков ассоциации.

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))
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top