Algorithm 我需要合并两个列表,对它们进行排序并删除重复项。有更好的方法吗?
我有两个未排序的列表,我需要生成另一个已排序的列表,其中所有元素都是唯一的 元素可以在两个列表中出现多次,并且它们最初是未排序的 我的函数如下所示:Algorithm 我需要合并两个列表,对它们进行排序并删除重复项。有更好的方法吗?,algorithm,sorting,lisp,list,Algorithm,Sorting,Lisp,List,我有两个未排序的列表,我需要生成另一个已排序的列表,其中所有元素都是唯一的 元素可以在两个列表中出现多次,并且它们最初是未排序的 我的函数如下所示: (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
(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))))
有没有更好的方法实现同样的目标
电话示例:
[CL]> (merge-lists '(9 8 4 8 9 7 2) '(1 7 3 9 2 6) #'>)
==> (9 8 7 6 4 3 2 1)
我想我应该首先对这两个列表分别排序,然后用一个函数合并它们,该函数也可以跳过重复项。这应该快一点,因为它需要两个列表少遍历一次
注:我怀疑它能做得更快,因为你基本上总是需要至少一次排序和一次合并。也许你可以将两者结合在一个函数中,但如果这没有(很大)区别的话,我不会感到惊讶。听起来你需要使用集合。我们的邻里友好型Lisp专家指出 他还提供了以下片段:
(defun merge-lists (list-a list-b sort-fn test-fn)
(sort (remove-duplicates (append list-a list-b) :test test-fn) sort-fn))
如果在合并列表之前对列表进行了排序,则可以同时合并、删除和排序列表。如果对它们进行了排序并且没有重复,那么merge/sort/duplicate remove函数就变得非常简单 事实上,最好更改insert函数,以便它执行排序插入以检查重复项。然后,您总是有没有重复的排序列表,合并它们是一件小事
同样,您可能更喜欢使用快速插入功能,但代价是以后对重复项进行排序/删除。如果在删除重复项之前应用排序,删除重复项功能是否会运行得更好?正如Antti指出的,您可能希望利用删除重复项和排序,虽然我可能会对测试函数使用关键字(或可选参数): (定义合并列表(列表-1列表-2排序fn和键(测试#'eql)) ...) 或 (定义合并列表(列表-1列表-2排序fn&可选(测试#'eql)) …)
这样,您就不必指定测试函数(由REMOVE-DUPLICATES用于测试“这些被认为是重复的吗”),除非EQL不够好。您可能想澄清“更好”的含义.你试过这个未经测试的代码段了吗?它成功了吗?我很想编辑我的答案,这样我们以后的几代人就不必担心代码段会破坏他们的Lisp 3000…我确实测试过它,它确实成功了。非常感谢你的回答。首先,
sort fn
是否与相等兼容?也就是说,(sort fn a b)
=NIL
和(sort fn b a)
=NIL
暗示(等于a b)
=T
?第二,你应该在排序
之后合并
,以提高速度。第三,sort fn
应该命名为比较
或类似的名称。我知道有一种优雅的方法:)这不是优雅的-这是列表长度的平方和,而不是最长列表长度的线性。集合通常不排序。RKitson有一点。如果集合很容易使用,那么一开始就不必处理重复的集合。另一方面,要使用集合,需要将dsm使用的动物映射到整数。这听起来很平常。我带着一个类似的问题来到这里,映射到整数并不容易,可能不容易。根据HyperSpec,它不需要对列表进行排序。