如何解决获得数字列表的相同奇偶校验
我正在根据第一个参数的奇数/偶数进行过滤列表的 SICP 练习。例如:
(same-parity 1 2 3 4 5 6 7)
; parity of first argument '1' is odd
; and we apply the 'odd' filter to the remaining list,(2 3 4 5 6 7)
(1 3 5 7)
这是我想出来的,但我遇到了一些麻烦:
; Helper function
(define (list-append lst elem)
(if (null? lst)
(cons elem nil)
(cons (car lst) (list-append (cdr lst) elem))))
; Actual function
(define (same-parity first . lst)
; start with an empty list,and we'll build it with side-effects
(define L '())
(define (same-parity-inner remaining-lst)
; when the list is exhausted,just return L
(cond ((null? remaining-lst) L)
; if the current element of the list has the same parity
; as the first element,add that to our list
(else (if (= (modulo first 2) (modulo (car remaining-lst) 2))
(list-append L (car remaining-lst)))
; and then recurse with the remaining list elements
(same-parity-inner (cdr remaining-lst)))))
(same-parity-inner lst))
现在我知道 SICP 问题有很多不错的解决方案,但我想知道是否有人可以指出我的实现的愚蠢之处,并帮助我找出更好的方法来做到这一点。
>更新,这是一个实现,它不是很好,但它是我拥有的第一个工作版本。我发现必须使用“实际列表”而不是 vargs 函数参数有点棘手,所以我编写了另一个内部函数来接受实际列表(也许有更好的方法来做到这一点?)。
; Helper
(define (append-list lst1 lst2)
(if (null? lst1)
lst2
(cons (car lst1) (append (cdr lst1) lst2))))
(define (same-par first . lst)
(define (same-par-inner lst)
(cond ((null? lst) '())
((= (modulo first 2) (modulo (car lst) 2)) (append-list (list (car lst)) (same-par-inner (cdr lst)) ))
(else (same-par-inner (cdr lst)))))
(same-par-inner lst))
(same-par 1 2 3 4 5 6 7 99 11)
; (3 5 7 99 11)
有没有办法在不定义内部函数的情况下递归地执行此操作?
解决方法
您可以使用 apply
进行递归调用,而无需使用辅助函数。它的最后一个参数是一个列表,它将在函数调用中扩展为参数。这允许您再次传递 first
以及 (cdr lst)
。
您也可以只使用 cons
从一个元素和一个后续列表构建一个新列表,而不是创建一个临时列表来使用 append-list
。
(define (same-par first . lst)
(cond ((null? lst) '())
((= (modulo first 2) (modulo (car lst) 2))
(cons (car lst)
(apply same-par first (cdr lst)) ))
(else (apply same-par first (cdr lst)))))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。