Удалить из " нелинейного списка " все повторяющиеся элементы (м.б., не атомы) на Lisp
Формулировка задачи:
> (rm '(1 (2 2 3) 4 (3 2 3) (8 9) 5 1 (8 9)) (2 2 3)) ==> ( 4 (3 2 3) 5)
Решение задачи: «Удалить из " нелинейного списка " все повторяющиеся элементы (м.б., не атомы) на Lisp»
(defun dump-top-level-duplicates (w &optional ac &aux (a (car w)) (d (cdr w))) (cond ((null w) (reverse ac)) ((member a d :test #'equalp) (dump-top-level-duplicates (remove a d :test #'equalp) ac)) (t (dump-top-level-duplicates d (cons a ac))))) > (dump-top-level-duplicates '(1 (2 2 3) 4 (3 2 3) (8 9) 5 1 (8 9) (2 2 3))) (4 (3 2 3) 5)
Объяснение кода листинга программы
В этом коде функция dump-top-level-duplicates принимает два аргумента: w, который является нелинейным списком, и необязательный аргумент ac, который является ассоциативным списком для хранения пар элементов, которые встречаются более одного раза. Функция возвращает новый список, который содержит только уникальные элементы из исходного списка.
Внутри функции используется конструкция cond, чтобы проверить, является ли w пустым. Если это так, то функция возвращает перевернутый список ac. Если w не пуст, то функция проверяет, является ли первый элемент a членом списка d с использованием функции member и теста equalp. Если это так, то функция вызывает себя для оставшейся части списка d и обновленного списка ac, который содержит пару элементов a и d. Если a не является членом d, то функция вызывает себя для d и нового списка ac, который содержит пару элементов a и d.
В данном примере функция вызывается с аргументом w, который является нелинейным списком (1 (2 2 3) 4 (3 2 3) (8 9) 5 1 (8 9) (2 2 3)). Функция находит повторяющиеся элементы (2 2 3) 4 (3 2 3) (8 9) и возвращает новый список (4 (3 2 3) 5).