我正在写一个递归函数(split L)
获取列表L
,并返回一个新列表
包含两个子列表,第一个子列表包含L
中的每个第二个元素
第二个列表包含不在第一个子列表中的其余元素。
下面 是如何的例子 分裂 应该工作:
(split ‘(1 2 3 4 5 6 7 8) ) ( (1 3 5 7) (2 4 6 8))
(split ‘(cat bird dog horse mouse pig tiger gerbil cow) )
( (cat dog mouse tiger cow) (bird horse pig gerbil))
现在这是我的尝试:
(define split
(lambda (L)
(if
(null? L)
'()
(list (first L) (second L))
)
)
)
(define first
(lambda (L)
(if
(null? L)
'()
(cond
(
(null? (cdr L))
(car L)
)
(
#t
(cons
(car L)
(first (cdr (cdr L)))
)
)
)
)
)
)
(define second
(lambda (L)
(if
(null? L)
'()
)
(cond
(
(null? (cdr L))
'()
)
(cons
(car (cdr L))
(second (cdr (cdr L)))
)
)
)
)
但不是我得到的预期结果:
对于(split '(1234))
,我得到((1234)())
。
对于(first '(1234))
,我得到(1234)
。
对于(second '(1234))
,我得到()
。
答案 0 :(得分:5)
需要考虑的一些事项:
cond
的最后一个条件中,您应该使用else
if
然后使用cond
,将所有条件都放在cond
中,它会让代码更清晰first
中的基本案例有误,您必须返回一个列表split
中,您应该使用list
来构建返回的列表,而不是cons
{}
括号 - 这将改善代码的可读性考虑到上述情况,这里有一个解决所有问题的实现:
(define split
(lambda (L)
(if (null? L)
'()
(list (first L) (second L)))))
(define first
(lambda (L)
(cond ((null? L) '())
((null? (cdr L)) L)
(else (cons (car L)
(first (cdr (cdr L))))))))
(define second
(lambda (L)
(cond ((null? L) '())
((null? (cdr L)) '())
(else (cons (car (cdr L))
(second (cdr (cdr L))))))))
现在它按预期工作:
(split '(1 2 3 4 5 6 7 8))
=> '((1 3 5 7) (2 4 6 8))
(split '(cat bird dog horse mouse pig tiger gerbil cow))
=> '((cat dog mouse tiger cow) (bird horse pig gerbil))
答案 1 :(得分:2)
我正在看这个并记住Merge Sort implementation from Rosetta Code for PicoLisp。在那里你只需要一个程序就可以同时执行奇数和偶数列表,对于这个问题也是如此。
;; makes a list of every other element
(define (alt lst)
(if (or (null? lst)
(null? (cdr lst)))
lst
(cons (car lst)
(alt (cddr lst)))))
;; no safeguard against empty list
;; needs at least one element.
(define (split lst)
(list (alt lst) (alt (cdr lst))))
(split '(1 2 3 4 5 6 7 8))
; ==> ((1 3 5 7) (2 4 6 8))
(split '(cat bird dog horse mouse pig tiger gerbil cow))
; ==> ((cat dog mouse tiger cow) (bird horse pig gerbil))
为了使零元素列表的安全性被遗漏为练习。