Eu preciso juntar duas listas, classificá-los e remover duplicatas. Existe uma maneira melhor de fazer isso?
Pergunta
Eu tenho duas listas não triados e preciso para produzir uma outra lista que é classificada e onde todos os elementos são únicos.
Os elementos podem ocorrer várias vezes em ambas as listas e eles são originalmente indiferenciado.
As minhas função seria algo parecido com isto:
(defun merge-lists (list-a list-b sort-fn)
"Merges two lists of (x, y) coordinates sorting them and removing dupes"
(let ((prev nil))
(remove-if
(lambda (point)
(let ((ret-val (equal point prev)))
(setf prev point)
ret-val))
(sort
(merge 'list list-a list-b sort-fn) ;'
sort-fn))))
Existe uma maneira melhor de conseguir o mesmo?
Chamada de amostra:
[CL]> (merge-lists '(9 8 4 8 9 7 2) '(1 7 3 9 2 6) #'>)
==> (9 8 7 6 4 3 2 1)
Solução
O nosso simpático bairro Lisp guru apontou a Remove-duplicatas funcionar .
Ele também forneceu o seguinte trecho:
(defun merge-lists (list-a list-b sort-fn test-fn)
(sort (remove-duplicates (append list-a list-b) :test test-fn) sort-fn))
Outras dicas
Eu acho que eu iria primeiro ordenar as duas listas separadamente e depois juntá-las com uma função que também salta sobre duplicatas. Este deve ser um pouco mais rápido, uma vez que requer um menor travessia de ambas as listas.
P.S .: duvido que pode ser feito muito mais rápido que você, basicamente, sempre precisa de pelo menos um tipo e uma mesclagem. Talvez você pode combinar os dois em uma função, mas eu não ficaria surpreso se isso não faz diferença (grande).
Se as listas são classificadas antes de fundi-los, eles podem ser mescladas, duplicado-removido e ordenados ao mesmo tempo. Se eles são classificadas e duplicar-livre, então o merge / sort / função duplicado-remove se torna realmente trivial.
Na verdade, talvez seja melhor mudar a sua função de inserção para que ele executa uma inserção ordenada que verifica a existência de duplicatas. Então você sempre tem listas ordenadas que são livres de duplicatas e fundi-las é uma questão trivial.
Então, novamente, você pode preferir ter uma função de inserção rápida ao custo de triagem / removendo duplicatas mais tarde.
não seria o Remove-duplicatas funcionar operar melhor se o tipo foi aplicado antes do Remove-duplicatas?
Como Antti apontou, você provavelmente vai querer alavancagem REMOVE-duplicatas e SORT, embora eu provavelmente usar uma palavra-chave (ou argumento opcional) para a função de teste: (Defun Merge-listas (lista-1 lista-2 espécie-fn & key (teste # eql ')) ...) ou (Defun Merge-listas (lista-1 lista-2 espécie-fn & opcional (teste # 'EQL) ...)
Desta forma, você não terá que especificar a função de teste (utilizado por Remover duplicatas de teste para "São essas duplicatas considerados"), a menos que EQL não é bom o suficiente.
Parece que você precisa estar usando conjuntos.