代码之家  ›  专栏  ›  技术社区  ›  dsm

我需要连接两个列表,对它们进行排序并删除重复项。有更好的方法吗?

  •  6
  • dsm  · 技术社区  · 18 年前

    我有两个未排序的列表,我需要生成另一个排序后的列表,其中所有元素都是唯一的。

    元素可以在两个列表中多次出现,并且它们最初没有排序。

    我的函数看起来像这样:

    (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)
    
    6 回复  |  直到 18 年前
        1
  •  11
  •   Antti Rasinen    18 年前

    我们邻里友好的Lisp大师指出 remove-duplicates function .

    他还提供了以下片段:

    (defun merge-lists (list-a list-b sort-fn test-fn)
        (sort (remove-duplicates (append list-a list-b) :test test-fn) sort-fn))
    
        2
  •  1
  •   mweerden    18 年前

    我想我会先分别对这两个列表进行排序,然后用一个也跳过重复项的函数将它们合并。这应该快一点,因为它需要少遍历两个列表一次。

    附言:我怀疑它能做得更快,因为你基本上总是需要至少一个排序和一个合并。也许你可以将两者结合在一个函数中,但如果这没有(很大)区别,我不会感到惊讶。

        3
  •  1
  •   aib    18 年前

    如果列表在合并之前已排序,则可以同时合并、删除重复项和排序。如果它们被排序并且没有重复,那么合并/排序/重复删除函数就变得非常简单。

    事实上,最好更改插入函数,使其执行排序插入以检查重复项。然后,您总是有没有重复项的排序列表,合并它们是一件小事。

    再者,您可能更喜欢使用快速插入功能,但代价是稍后对重复项进行排序/删除。

        4
  •  0
  •   jdkoftinoff    18 年前

    如果在删除重复项之前应用排序,那么删除重复项的功能不是会更好吗?

        5
  •  0
  •   Vatine    17 年前

    正如Antti所指出的,您可能希望利用REMOVE-DULICATES和SORT,尽管我可能会在测试函数中使用关键字(或可选参数): (取消合并列表(列表-1列表-2排序fn&key(test#'eql)) ...) 或 (defun合并列表(列表-1列表-2排序fn和可选(test#'eql)) ...)

    这样,您就不必指定测试函数(REMOVE-DULICATES使用该函数来测试“这些是否被视为重复”),除非EQL不够好。

        6
  •  -2
  •   RKitson    18 年前

    听起来你需要使用Set。