我想使用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))))))
功能输入K
和L
是已排序的关联列表。
例如,
K
是((1 . a) (3 . c) (5 . e))
L
是((2 . b) (4 . d))
。
我预计结果为((1 . a) (2 . b) (3 . c) (4 . d) (5 . e))
。
但结果完全不同。 为什么会出现这个结果? 感谢。
答案 0 :(得分:2)
你可以稍微简化一下。主要的变化就像是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))
答案 1 :(得分:0)
(cons K (MERGEALIST (cdr K) L))
在这里,您将完整的列表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
。