例如,如果我创建一个名为odd-places的函数,它应该按如下方式工作,
(odd-places '(p q r s t 1 2)) = (p r t 2)
可以使用递归来完成吗? 谢谢。
答案 0 :(得分:1)
类似Scheme的语言中的基本列表尾递归模式是:
null?
测试停止递归 i
必须是偶数(因为它从1开始而不是0) 应用这个给我们
(define (odd-places lst)
(define (remove-rec lst i)
(cond ((null? lst) '())
((odd? i) (cons (car lst) (remove-rec (cdr lst) (+ i 1))))
(else (remove-rec (cdr lst) (+ i 1))))) // i is even, skip this element!
(remove-rec lst 1))
答案 1 :(得分:1)
这是一种递归方法,通过使用两个相互递归函数来解决任务。在这种方法中,不需要辅助变量,检查奇数或均匀度。
(define (odd-places lst)
(define (get lst)
(if (null? lst)
'()
(cons (car lst) (dont-get (cdr lst)))))
(define (dont-get lst)
(if (null? lst)
'()
(get (cdr lst))))
(get lst))
第一个函数get
列表中的第一个项目,并将第二个函数的结果应用于列表的其余部分,dont-get
列表的第一个元素立即返回第一个函数应用于列表的其余部分。
这个版本在堆栈使用的空间和执行时间方面比HyperZ的答案中的经典递归更有效。
最后,考虑到前面的解决方案是如何工作的,我们可以解决在单个递归调用中“折叠”两个内部函数的问题,而不需要辅助函数或变量:
(define (odd-places lst)
(cond ((null? lst) '())
((null? (cdr lst)) (list (car lst)))
(else (cons (car lst) (odd-places (cddr lst))))))
答案 2 :(得分:1)
您的示例实际上是显示列表中的 even 元素,因为第0个(偶数)元素是p
。这就是为什么下面的解决方案使用even?
。
其他答案都有针对性的递归解决方案,但您没有说明为什么需要它递归。如果您只是想要一种简洁的方法来获得替代品,那么“理解”也可以起作用:
(for/list ([i (length lst)] #:when (even? i))
(list-ref lst i))
答案 3 :(得分:1)
比以前的答案更短的版本:
(define (odd-places lst)
(if (or (null? lst) (null? (cdr lst)))
lst
(cons (car lst) (odd-places (cddr lst)))))
测试:
> (odd-places '(p q r s t 1 2))
'(p r t 2)
答案 4 :(得分:0)
一个小小的附录:使用此功能,您可以选择列表中应跳过的项目,然后再将其包含在结果列表中。
(define (nth-places n lst [i 0])
(cond
[(null? lst) null]
[(= i 0) (cons (car lst)
(nth-places n (cdr lst) (+ i 1)))]
[(= i n) (nth-places n (cdr lst) 0)]
[else (nth-places n (cdr lst) (+ i 1))]))
i
中的[i 0]
是一个可选参数,您不必在调用函数时指定它,因为在这种情况下它具有设置的起始值0。这里i
用作累加器索引,我们从零开始计数而不是一个。
n
定义只应选择所有第n个元素来构建新列表,我们再次开始索引为0。
如果你想生产像这里的交替元素
(odd-places '(p q r s t 1 2)) = (p r t 2)
你会打电话给
(nth-places 1 '(p q r s t 1 2))
对于每个第三个元素集n到2,依此类推。