如何管理方案中关于添加和计数的任意列表
How to manage arbitrary list in scheme in regard to adding and counting numbers
所以我已经创建了基本功能
(define (countNumbers lst)
(cond
((null? lst) 0)
((number? (car lst))(+ 1 (countNumbers (cdr lst))))
(else (countNumbers (cdr lst)))))
(define (sumNumbers lst)
(cond
((null? lst) 0)
((number? (car lst))(+ (car lst) (sumNumbers (cdr lst))))
(else (sumNumbers (cdr lst)))))
现在有没有办法,你如何让这些函数适用于任意列表,就像我传入 (1 (2 (3))) 给 countNumbers it returns 3 如果我把它传入sumNumbers 它 returns 6?
您可以只添加第二级递归,如下所示:
(define (countNumbers lst)
(cond
((null? lst) 0)
((number? (car lst))(+ 1 (countNumbers (cdr lst))))
((list? (car lst)) (+ (countNumbers (car lst)) (countNumbers (cdr lst))))
(else (countNumbers (cdr lst)))))
(define (sumNumbers lst)
(cond
((null? lst) 0)
((number? (car lst))(+ (car lst) (sumNumbers (cdr lst))))
((list? (car lst)) (+ (sumNumbers (car lst)) (sumNumbers (cdr lst))))
(else (sumNumbers (cdr lst)))))
这与 有关。本质上,你只需要应用标准模板来遍历列表列表,根据问题做适当的事情:
- 测试
null?
列表,基本情况。
- 测试当前元素是否为
pair?
,在这种情况下,我们必须重复 car
和 cdr
并组合答案。
- 否则,我们在一个原子中。
此外,对于您提到的功能,我们必须测试另一种情况:如果当前原子是或不是 number?
;而这里合并的方式是将结果相加。例如:
(define (countNumbers lst)
(cond ((null? lst) 0)
((pair? lst)
(+ (countNumbers (car lst))
(countNumbers (cdr lst))))
((number? lst) 1)
(else 0)))
(define (sumNumbers lst)
(cond ((null? lst) 0)
((pair? lst)
(+ (sumNumbers (car lst))
(sumNumbers (cdr lst))))
((number? lst) lst)
(else 0)))
它按预期工作:
(countNumbers '(1 x (x 2) x (3 (4 x (5) 6) 7)))
=> 7
(sumNumbers '(1 x (x 2) x (3 (4 x (5) 6) 7)))
=> 28
更高层次的抽象
与其使用起源于 IBM 704 机器指令的较低级别的运算符 car
和 cdr
,countNumbers
可以在更高的抽象级别上实现使用 function composition and sequences as conventional interfaces as described in The Structure and Interpretation of Computer Programs:
(define (countNumbers lox)
(length (filter number? (flatten lox))))
实施展平
flatten
是一个常见的列表操作。但它不包括在方案标准中。
来自 Rosetta Code:
(define (flatten x)
(cond ((null? x) '())
((not (pair? x)) (list x))
(else (append (flatten (car x))
(flatten (cdr x))))))
flatten
中内置的 #lang racket
的 source 提供了基于迭代和 cons
:
的更快实现
(define (flatten orig-sexp)
(let loop ([sexp orig-sexp] [acc null])
(cond [(null? sexp) acc]
[(pair? sexp) (loop (car sexp) (loop (cdr sexp) acc))]
[else (cons sexp acc)])))
在 R5RS 方案中,这将是:
(define (flatten orig-sexp)
(letrec
((loop (lambda (sexp acc)
(cond ((null? sexp) acc)
((pair? sexp)
(loop (car sexp)
(loop (cdr sexp) acc)))
(else (cons sexp acc))))))
(loop orig-sexp '())))
所以我已经创建了基本功能
(define (countNumbers lst)
(cond
((null? lst) 0)
((number? (car lst))(+ 1 (countNumbers (cdr lst))))
(else (countNumbers (cdr lst)))))
(define (sumNumbers lst)
(cond
((null? lst) 0)
((number? (car lst))(+ (car lst) (sumNumbers (cdr lst))))
(else (sumNumbers (cdr lst)))))
现在有没有办法,你如何让这些函数适用于任意列表,就像我传入 (1 (2 (3))) 给 countNumbers it returns 3 如果我把它传入sumNumbers 它 returns 6?
您可以只添加第二级递归,如下所示:
(define (countNumbers lst)
(cond
((null? lst) 0)
((number? (car lst))(+ 1 (countNumbers (cdr lst))))
((list? (car lst)) (+ (countNumbers (car lst)) (countNumbers (cdr lst))))
(else (countNumbers (cdr lst)))))
(define (sumNumbers lst)
(cond
((null? lst) 0)
((number? (car lst))(+ (car lst) (sumNumbers (cdr lst))))
((list? (car lst)) (+ (sumNumbers (car lst)) (sumNumbers (cdr lst))))
(else (sumNumbers (cdr lst)))))
这与
- 测试
null?
列表,基本情况。 - 测试当前元素是否为
pair?
,在这种情况下,我们必须重复car
和cdr
并组合答案。 - 否则,我们在一个原子中。
此外,对于您提到的功能,我们必须测试另一种情况:如果当前原子是或不是 number?
;而这里合并的方式是将结果相加。例如:
(define (countNumbers lst)
(cond ((null? lst) 0)
((pair? lst)
(+ (countNumbers (car lst))
(countNumbers (cdr lst))))
((number? lst) 1)
(else 0)))
(define (sumNumbers lst)
(cond ((null? lst) 0)
((pair? lst)
(+ (sumNumbers (car lst))
(sumNumbers (cdr lst))))
((number? lst) lst)
(else 0)))
它按预期工作:
(countNumbers '(1 x (x 2) x (3 (4 x (5) 6) 7)))
=> 7
(sumNumbers '(1 x (x 2) x (3 (4 x (5) 6) 7)))
=> 28
更高层次的抽象
与其使用起源于 IBM 704 机器指令的较低级别的运算符 car
和 cdr
,countNumbers
可以在更高的抽象级别上实现使用 function composition and sequences as conventional interfaces as described in The Structure and Interpretation of Computer Programs:
(define (countNumbers lox)
(length (filter number? (flatten lox))))
实施展平
flatten
是一个常见的列表操作。但它不包括在方案标准中。
来自 Rosetta Code:
(define (flatten x)
(cond ((null? x) '())
((not (pair? x)) (list x))
(else (append (flatten (car x))
(flatten (cdr x))))))
flatten
中内置的 #lang racket
的 source 提供了基于迭代和 cons
:
(define (flatten orig-sexp)
(let loop ([sexp orig-sexp] [acc null])
(cond [(null? sexp) acc]
[(pair? sexp) (loop (car sexp) (loop (cdr sexp) acc))]
[else (cons sexp acc)])))
在 R5RS 方案中,这将是:
(define (flatten orig-sexp)
(letrec
((loop (lambda (sexp acc)
(cond ((null? sexp) acc)
((pair? sexp)
(loop (car sexp)
(loop (cdr sexp) acc)))
(else (cons sexp acc))))))
(loop orig-sexp '())))