Удалить дубликаты по значению из списка в Common Lisp - PullRequest
0 голосов
/ 17 декабря 2018

Учитывая два списка, составленных из нескольких «объектов» в следующем формате: (name id) как я могу получить объекты из первого списка, которые не совпадают по имени со вторым?

Ожидаемый результат:

(remove-duplicates-by-name
  '((Oliver 1) (Charlie 2) (Oscar 20))
  '((Oliver 2)(Charlie 3)))

((Oscar 20))

(remove-duplicates-by-name 
  '((Oliver 1)) 
  '((Oliver 2)(Charlie 3)))

()

(remove-duplicates-by-name 
  '() 
  '((Oliver 2)(Charlie 3)))

()

Редактировать:

Порядок вывода имеет значение. Пример:

(remove-duplicates-by-name 
  '((Oliver 1) (Charlie 2) (Oscar 20) (Daniel 30)) 
  '((Oliver 2)(Charlie 3)))

Правильный вывод: ((Oscar 20)(Daniel 30))

Неверный вывод: ((Daniel 30)(Oscar 20))

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Вот два хакерских решения.

(defun remove-duplicates-by-name (l to-remove)
  ;; low performance with large to-remove lists but fine with short
  ;; ones
  (loop for e in l
        unless (assoc (car e) to-remove)
        collect e))

(defun remove-duplicates-by-name (l to-remove)
  ;; high performance with large to-remove lists but consy and
  ;; probably slow with short ones
  (loop with dups = (loop with dt = (make-hash-table)
                          for e in to-remove
                          do (setf (gethash (car e) dt) t)
                          finally (return dt))
        for e in l
        unless (gethash (car e) dups)
        collect e))
0 голосов
/ 17 декабря 2018

Ваши примеры не имеют ничего общего с дубликатами , но имеют отношение к Спискам в виде наборов .

Например:

(set-difference '((Oliver 1) (Charlie 2) (Oscar 20)) '((Oliver 2)(Charlie 3)) :key #'car)
==> ((Oscar 20))

(set-difference '((Oliver 1)) '((Oliver 2)(Charlie 3)) :key #'car)
==> ()

(set-difference '() '((Oliver 2)(Charlie 3)) :key #'car)
==> ()
...