List 如何递归地获取列表中的偶数元素
我试图创建一个函数,返回列表中的偶数元素 例如:List 如何递归地获取列表中的偶数元素,list,scheme,List,Scheme,我试图创建一个函数,返回列表中的偶数元素 例如: (evens '(a b c d)) (evens '(a b c d e)) 应该回来 (b d) 下面的代码似乎适用于包含奇数和奇数个元素的列表,但是如果我给它一个包含偶数个元素的列表,它是不正确的 例如: (evens '(a b c d)) (evens '(a b c d e)) 会回来的 (b d) 但是: (evens '(a b c d)) 会回来的 (a c) 有什么想法吗 将我的代码更改为: (DEFINE
(evens '(a b c d))
(evens '(a b c d e))
应该回来
(b d)
下面的代码似乎适用于包含奇数和奇数个元素的列表,但是如果我给它一个包含偶数个元素的列表,它是不正确的
例如:
(evens '(a b c d))
(evens '(a b c d e))
会回来的
(b d)
但是:
(evens '(a b c d))
会回来的
(a c)
有什么想法吗
将我的代码更改为:
(DEFINE (evens lis)
(cond
((null? lis) '())
(else (cons (cadr lis) (evens (cdr lis))))
))
获取一个错误,表示传递给安全车的对象不是一对?问题是,如果列表中的元素数为偶数,则会匹配
模
分支,然后开始cons
与列表中的车
匹配。。。因此,在您的示例中,您得到了a
,依此类推
但是,更重要的是,对于此函数,您不需要使用length
。。。您不应该这样做:因为length
在列表长度中需要线性时间,evens
现在需要二次时间
建议:您的程序应该“记住”在每个递归步骤中它是处于“奇数”还是“偶数”位置。。。您是如何做到这一点的(有几种方法)?您的代码缺少一些检查,并且有一些不正确的逻辑
(define (evens lis)
(cond
((null? lis) '())
((eq? (cdr lis) '()) '()) ;missing condition
(else (cons (cadr lis) (evens (cddr lis)))))) ; it is cddr not cdr
在过去的几天里,也有人问过同样的问题。这一次我会给出一个直接的回答,直截了当地说:
(define (evens lst)
(if (or (null? lst) ; if the list is empty
(null? (cdr lst))) ; or the list has a single element
'() ; then return the empty list
(cons (cadr lst) ; otherwise `cons` the second element
(evens (cddr lst))))) ; and recursively advance two elements
下面是如何首先进行一些错误检查:
(define (find-evens lst)
(if (list? lst)
(evens lst)
(error "USAGE: (find-evens [LIST])")))
我将用评论过的例子来回答你的问题,希望你能真正学到一些东西,而不仅仅是给你一些有用的代码。事实上,如果您对scheme还不熟悉,那么查看几段代码可能会更有启发性 您最初的定义如下所示:
(define (evens lis)
(cond (;; Check: Recursion stop condition
(null? lis)
'())
(;; Wrong: Calling length at each step => O(n^2)
;; Wrong: Assuming even element if list has even number of elements
(= (modulo (length lis) 2) 0)
;; Wrong: Recursing with the rest of the list, you'll get odds
(cons (car lis) (evens (cdr lis))))
(else
;; Wrong: Recursing with the rest of the list with cdr, you'll get odds
(evens (cdr lis)))))
(define (evens lis)
(cond (;; Check: Recursion stop condition
(null? lis)
'())
(else
;; Check: Building list with second element
;; Wrong: If lis only has 1 element,
;; (cdr lis) is null and (car (cdr list)) is an error.
(cons (cadr lis)
;; Wrong: Recursing with cdr, you'll get odds
(evens (cdr lis))))))
之后,您编辑了问题,将其更新为以下内容:
(define (evens lis)
(cond (;; Check: Recursion stop condition
(null? lis)
'())
(;; Wrong: Calling length at each step => O(n^2)
;; Wrong: Assuming even element if list has even number of elements
(= (modulo (length lis) 2) 0)
;; Wrong: Recursing with the rest of the list, you'll get odds
(cons (car lis) (evens (cdr lis))))
(else
;; Wrong: Recursing with the rest of the list with cdr, you'll get odds
(evens (cdr lis)))))
(define (evens lis)
(cond (;; Check: Recursion stop condition
(null? lis)
'())
(else
;; Check: Building list with second element
;; Wrong: If lis only has 1 element,
;; (cdr lis) is null and (car (cdr list)) is an error.
(cons (cadr lis)
;; Wrong: Recursing with cdr, you'll get odds
(evens (cdr lis))))))
解决方案是检查列表是否至少有第二个元素:
(define (evens lis)
(cond (;; Check: Recursion stop condition 1
(null? lis)
'())
(;; Check: Recursion stop condition 2: list of length = 1
(null? (cdr lis))
'())
(else
;; Check: Building list with second element
;; The previous cond clauses have already sorted out
;; that lis and (cdr lis) are not null.
(cons (cadr lis)
;; Check: Recurse "the rest of the rest" of lis with cddr
(evens (cddr lis)))))
练习:使用
if
和或
将此解决方案简化为只有两个分支。逐步执行代码,错误应该很明显。(在第一次迭代中)您应该添加新代码,而不是替换旧代码。现在这个问题已经不完整了,部分问题已经不相关了。可能是一个相关的、意气相投的问题的重复。强烈推荐!!在Scheme中,您需要cddr
功能。此问题是否可以标记为重复问题?或者更确切地说,其他问题,因为这一个似乎吸引了更多的注意力和答案?@PauloMadeira我已经将这一个标记为重复,只剩下第一个问题。