List 在公共Lisp中合并两个列表

List 在公共Lisp中合并两个列表,list,merge,lisp,common-lisp,List,Merge,Lisp,Common Lisp,有没有一种有效的方法可以在Lisp中合并两个列表,这样如果它们有公共元素,那么这些元素只会出现在结果列表中一次 目前,我有以下代码: (defun divisible-by-5 (num) (zerop (mod num 5))) (defun divisible-by-3 (num) (zerop (mod num 3))) (remove-if-not #'dividable-by-5 '(loop for i from 1 upto 10 collect i)) (remove

有没有一种有效的方法可以在Lisp中合并两个列表,这样如果它们有公共元素,那么这些元素只会出现在结果列表中一次

目前,我有以下代码:

(defun divisible-by-5 (num)
  (zerop (mod num 5)))

(defun divisible-by-3 (num)
  (zerop (mod num 3)))

(remove-if-not #'dividable-by-5 '(loop for i from 1 upto 10 collect i))
(remove-if-not #'divisible-by-3 '(loop for i from 1 upto 10 collect i))

我想将底部表单返回的两个列表以上述方式合并到上。

您已经收集了两次列表(1…n),然后创建 删除某些元素的新列表,然后进行组合 那些名单。如果你在寻找高效的,你可能应该结合 生成初始列表、测试和收集的过程:

(flet ((by-5 (n)
         (zerop (mod n 5)))
       (by-3 (n)
         (zerop (mod n 3))))
  (loop for x from 1 to 50
     unless (and (by-3 x)
                 (by-5 x))
     collect x))
但是如果你真的想单独收集列表,然后合并 他们,你可以通过工会做到这一点:

(flet ((by-5 (n)
         (zerop (mod n 5)))
       (by-3 (n)
         (zerop (mod n 3))))
  (let ((fives (loop for x from 1 to 50 unless (by-5 x) collect x))
        (threes (loop for x from 1 to 50 unless (by-5 x) collect x)))
    (union fives threes)))
现在,工会不能保证维护秩序,但在这种情况下,因为 您知道您的列表已经排序,您可以将它们合并为一个列表 更有效一点,因为您可以比较元素,并且知道 在某一点之后,您不会遇到重复:

(defun merge-unique (l1 l2 predicate)
  "Returns the result of merging L1 and L2, with no duplicates.
L1 and L2 should already be sets (that is, containing no duplicates), 
and should be ordered according to PREDICATE.  The tail of the result
may be shared with with either L1 or L2."
  (labels ((test (x y)
             (funcall predicate x y))
           (%merge (l1 l2 result)
             "Tail recursive merge procedure.  This could be converted
              to an iterative DO-loop without too much touble."
             (cond
               ((endp l1)
                (nreconc result l2))
               ((endp l2)
                (nreconc result l1))
               ((destructuring-bind (x . xs) l1
                  (destructuring-bind (y . ys) l2
                    (cond
                      ((test x y)
                       (%merge xs l2 (list* x result)))
                      ((test y x)
                       (%merge l1 ys (list* y result)))
                      (t
                       (%merge xs ys (list* x result))))))))))
    (%merge l1 l2 '())))
以下是其使用示例:

(merge-unique '(1 3 5 6) '(1 4 5 6) '<)
;;=> (1 3 4 5 6)
(合并唯一的“(1 3 5 6)”(1 4 5 6)”(1 3 4 5 6)

您已经收集了两次列表(1…n),然后创建 删除某些元素的新列表,然后进行组合 这些列表。如果你在寻找高效的,你可能应该结合 生成初始列表、测试和收集的过程:

(flet ((by-5 (n)
         (zerop (mod n 5)))
       (by-3 (n)
         (zerop (mod n 3))))
  (loop for x from 1 to 50
     unless (and (by-3 x)
                 (by-5 x))
     collect x))
但是如果你真的想单独收集列表,然后合并 他们,你可以通过工会做到这一点:

(flet ((by-5 (n)
         (zerop (mod n 5)))
       (by-3 (n)
         (zerop (mod n 3))))
  (let ((fives (loop for x from 1 to 50 unless (by-5 x) collect x))
        (threes (loop for x from 1 to 50 unless (by-5 x) collect x)))
    (union fives threes)))
现在,工会不能保证维护秩序,但在这种情况下,因为 您知道您的列表已经排序,您可以将它们合并为一个列表 更有效一点,因为您可以比较元素,并且知道 在某一点之后,您不会遇到重复:

(defun merge-unique (l1 l2 predicate)
  "Returns the result of merging L1 and L2, with no duplicates.
L1 and L2 should already be sets (that is, containing no duplicates), 
and should be ordered according to PREDICATE.  The tail of the result
may be shared with with either L1 or L2."
  (labels ((test (x y)
             (funcall predicate x y))
           (%merge (l1 l2 result)
             "Tail recursive merge procedure.  This could be converted
              to an iterative DO-loop without too much touble."
             (cond
               ((endp l1)
                (nreconc result l2))
               ((endp l2)
                (nreconc result l1))
               ((destructuring-bind (x . xs) l1
                  (destructuring-bind (y . ys) l2
                    (cond
                      ((test x y)
                       (%merge xs l2 (list* x result)))
                      ((test y x)
                       (%merge l1 ys (list* y result)))
                      (t
                       (%merge xs ys (list* x result))))))))))
    (%merge l1 l2 '())))
以下是其使用示例:

(merge-unique '(1 3 5 6) '(1 4 5 6) '<)
;;=> (1 3 4 5 6)
(合并唯一的“(1 3 5 6)”(1 4 5 6)”(1 3 4 5 6)

函数UNION如何?@sds这个问题是关于如何实现自己的
UNION
函数,而不是使用内置函数。为什么是“可分割”和“可分割”?@Barmar:你是对的;但是,这个问题除了提到
union
的另一个问题的一个答案之外,没有额外的见解。你的列表已经排序,你可以调用
merge
并删除在一次传递中唯一的值(并且只保留一个重复项).UNION函数如何?@sds这个问题是关于如何实现自己的
UNION
函数,而不是使用内置函数。为什么是“可分割”和“可分割”?@Barmar:你是对的;但是,这个问题除了提到
union
的另一个问题的一个答案之外,没有额外的见解。你的列表已经排序,你可以调用
merge
并删除在一次传递中唯一的值(并且只保留一个重复项).merge unique是否需要一个特殊的模块?我的CL说它是未定义的。@Mad这不是一个库函数。我刚刚编写了它。它的代码在答案中。最后一个参数做什么,以及如何在函数中分析它?@Mad它是用于检查一个元素是否小于另一个元素的谓词函数。因为我们在保持列表排序时,我们知道如果x是否需要一个特殊的模块?我的CL说它是未定义的。@Mad这不是一个库函数。我刚刚编写了它。它的代码在答案中。最后一个参数做什么,以及如何在函数中分析它?@Mad它是用于检查一个元素是否小于另一个元素的谓词函数。因为我们在保持列表排序时,我们知道如果x