Хитрость заключается в том, чтобы перебрать второй список, подсчитав, сколько вещей вы встретите в первом.Функция member
позволяет вам выполнить этот тест, поэтому вы можете выбрать один из следующих двух вариантов:
;; A version with explicit recursion down the list
;;
;; This will blow its stack if list is too long.
(defun count-known-atoms (known list)
"Return how many of the elements of `list' are atoms and appear
in `known'."
(if (null list)
0
(let ((hd (car list)))
(+ (if (and (atom hd) (member hd known)) 1 0)
(count-known-atoms known (cdr list))))))
;; A version using local variables and side effects. Less pretty, if you're a
;; fan of functional programming, but probably more efficient.
(defun count-known-atoms-1 (known list)
"Return how many of the elements of `list' are atoms and appear
in `known'."
(let ((count 0))
(dolist (x list count)
(when (and (atom x) (member x known))
(setq count (1+ count))))))
;; (count-known-atoms '(1 2) '(0 1 2 3 4 5)) => 2
;; (count-known-atoms-1 '(1 2) '(0 1 '(2) 3 4 5)) => 1
Если в ELisp была функция sum
для суммирования по списку или какой-то fold
, другой вариант - отобразить второй список, чтобы получить нули и единицы, а затем сдавить их.Я не думаю, что это так, поэтому я бы предложил count-known-atoms-1
.