我试图在Racket / Scheme中构建一个函数,在这里你得到一个整数列表,然后它必须将它们分成两个子列表,一个用于偶数,一个用于奇数。我是一个非常新的球拍,我有一些基本的操作列表,但我无法弄清楚如何定义两个子列表并在每个子列表中放置数字。
这是我到目前为止所做的:
(define (segregate lst)
(if (empty? lst)
'()
(if (even? (car a lst))
(append (car alst) (segregate (cdr alst))))
从那里我被卡住了。因此,如果条件,偶数将被分类到一个列表中。但我也需要奇数。在这种情况下的else语句会给你那些奇数,但我不知道如何将它们放入一个单独的列表中。
这是我第一次真实地在这个网站上提问,因为我的教授出于某种原因不在他的办公室。
答案 0 :(得分:1)
所以,你的函数需要返回两个列表,对吧?你的基本案例需要返回两个空列表,然后在递归的情况下,你需要填写相关的列表。这是一些骨架代码(填写<???>
):
(define (odds-and-evens lst)
(if (null? lst)
(values '() '())
(let-values (((odds evens) (odds-and-evens (cdr lst))))
(cond ((odd? (car lst)) (values (cons <???> <???>) <???>))
((even? (car lst)) (values <???> (cons <???> <???>)))
(else (values odds evens))))))
答案 1 :(得分:1)
克里斯&#39; let-values
- 版本很辣,但我会这样编写它以使其尾递归:
(define (split left? lst)
(let loop ((lst lst) (a '()) (b '()))
(if (null? lst)
;; you don't need to use values. `cons` or `list` are sometimes preferred
(values (reverse a) (reverse b))
(let ((e (car lst)))
(if (left? e)
(loop (cdr <???>) (cons <???> <???>) <???>)
(loop (cdr <???>) <???> (cons <???> <???>)))))))
(split odd? '(1 2 3 4 ...))
; ==>
; (1 3 ...)
; (2 4 ...)
即使它遍历两个列表两次(一个用于分离而另一个用于反向),它仍然快了很多倍,并且IMO更容易遵循。
如果您不关心订单,那么您只需跳过reverse
步骤,它就会更快。
答案 2 :(得分:1)
以上代码令人困惑。 Racket是一种非常简单的语言,它旨在了解代码在您阅读时所执行的操作。您可以使用尾递归来解决此问题。
分析A的第一个元素,将其放在应该的位置,然后再次调用该函数,直到A为空。
(define segregate
(lambda (A o e) ;A is the list of integers, o is the list of odds and e is for evens.
(cond ((empty? A) (list o e))
((even? (car A)) (segregate (cdr A) o (append e (car A)))
(else (segregate (cdr A) (append o (car A)) e)))))
答案 3 :(得分:1)
使用内置partition
:
(define (segregate lst)
(let-values ([(e o) (partition even? lst)])
(list e o)))
答案 4 :(得分:1)
另一种选择是使用foldr
(define (odd-even xs)
(foldr (lambda (x b)
(if (odd? x)
(list (cons x (first b)) (second b))
(list (first b) (cons x (second b))))) '(()()) xs))
racket@> (odd-even '(1 2 3 4 5 6 7))
'((1 3 5 7) (2 4 6))