【问题标题】:Merging Two Lists in Common Lisp在 Common Lisp 中合并两个列表
【发布时间】:2017-02-23 03:05:27
【问题描述】:

有没有一种有效的方法可以在 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))

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

【问题讨论】:

  • 函数UNION怎么样?
  • @sds 这个问题是关于如何实现自己的union函数而不是使用内置函数。
  • 为什么“可分”“可分”?
  • @Barmar:你是对的;但是,除了提到 union 的其他问题的答案之一之外,这个问题没有任何额外的见解。
  • 您的列表已排序,您可以调用merge 并删除单次传递中唯一的值(并仅保留其中一个重复项)。

标签: list merge lisp common-lisp


【解决方案1】:

您已经收集列表 (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))

但是如果你真的想单独收集列表然后合并 他们,你可以用 UNION 做到这一点:

(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)

【讨论】:

  • merge-unique 是否需要特殊模块?我的 CL 说它是未定义的。
  • @madphysicist 这不是库函数。我刚写的。它的代码在答案中。
  • 最后一个参数有什么作用,在函数内部如何分析?
  • @Mad 它是用于检查一个元素是否小于另一个元素的谓词函数。由于我们保持列表排序,我们知道如果 x
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-31
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2022-10-04
相关资源
最近更新 更多