【问题标题】:I want to merge and sort two sorted lists with Common Lisp我想用 Common Lisp 合并和排序两个排序列表
【发布时间】:2016-04-08 10:52:00
【问题描述】:

我想用 Common Lisp 合并和排序两个排序的关联列表。 我做了代码。但结果和我想的不一样。

(defun MERGEALIST (K L)
  (cond ((and (eq nil K) (eq nil L)) nil)
        ((eq nil K) L)
        ((eq nil L) K)
        ((<= (car (car K)) (car (car L)))
         (cons K (MERGEALIST (cdr K) L)))
        ((> (car (car K)) (car (car L)))
         (cons L (MERGEALIST K (cdr L))))))

函数的输入KL 是排序的关联列表。 例如,

K((1 . a) (3 . c) (5 . e))

L((2 . b) (4 . d))

我预计结果是((1 . a) (2 . b) (3 . c) (4 . d) (5 . e))

但结果完全不同。 为什么会出现这个结果? 谢谢。

【问题讨论】:

  • 尝试将最后两种情况下的(cons k ...)(cons l ...)更改为(cons (car k) ...)(cons (car l) ...)
  • 我很确定您在之前的问题中得到了答案:stackoverflow.com/q/36457071/1281433。您在此处接受的答案(使用标准函数 merge)在an answer 中进行了描述(免责声明,这是我的答案)。
  • @JoshuaTaylor:MERGE 的答案只是补充。我在第一部分专门用他的代码回答了他的问题。我认为他的问题不是关于哪个现有函数解决了它,而是他如何让代码工作......

标签: lisp common-lisp


【解决方案1】:

你可以稍微简化一下。主要变化就像来自 jkiiski 的评论。

CL-USER 5 > (defun MERGEALIST (K L)
              (cond ((and (null K) (null L)) nil)
                    ((null K) L)
                    ((null L) K)
                    ((<= (caar K) (caar L))
                     (cons (car K) (MERGEALIST (cdr K) L)))
                    ((> (caar K) (caar L))
                     (cons (car L) (MERGEALIST K (cdr L))))))
MERGEALIST

CL-USER 6 > (mergealist '((1 . a) (3 . c) (5 . e)) '((2 . b) (4 . d)))
((1 . A) (2 . B) (3 . C) (4 . D) (5 . E))

内置函数merge做到了:

CL-USER 9 > (merge 'list
                   '((1 . a) (3 . c) (5 . e))
                   '((2 . b) (4 . d))
                   #'<
                   :key #'car)
((1 . A) (2 . B) (3 . C) (4 . D) (5 . E))

【讨论】:

    【解决方案2】:
    (cons K (MERGEALIST (cdr K) L))
    

    在这里,您将 complete 列表 K 放在计算的“其余部分”前面。您只需要它的第一个元素(您刚刚测试“出现在”L 的第一个元素之前):

    (cons (car K) (MERGEALIST (cdr K) L))
    

    请注意,您可以简化很多:

    (defun merge-alists (k l)
      (cond 
        ;; Common case first, if both alists are not empty, then select
        ;; the first element of that alist, whose car is less. Then, recurse.
        ((and (consp k) (consp l))
             (if (<= (caar k) (caar l))
               (cons (car k) (merge-alists (cdr k) l))
               (cons (car l) (merge-alists k (cdr l)))))
        ;; One of the alists is empty, use either the not-empty one or ...
        ((consp k) k)
        ;; ... just the other (when k is empty or both are empty)
        (t l)))
    

    (最后两个 cond 子句可以简化为 (t (or k l)) ......但这可能有点过于简洁而难以清晰理解。)

    或者,如前所述,使用merge

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 1970-01-01
      • 2015-05-12
      • 2017-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      相关资源
      最近更新 更多