在方案中给出一个数字流,我需要打印 n 个用逗号分隔的数字,例如 (1, 2, 3, 4, ..)
Give a stream of numbers in scheme I need to print n numbers separated by comma like (1, 2, 3, 4, ..)
我可以使用以下代码将 n 个数字打印为列表:
(define (print-first-n stream1 n)
(cond((= n 0) '())
(else(cons(stream-car stream1) (print-first-n (stream-cdr stream1) (- n 1))))))
但是我不知道如何添加逗号。
你不能在普通列表中打印逗号,但我们可以用流的内容构建一个字符串,用逗号分隔。这将起作用,假设字符串包含 numbers:
(define (print-first-n stream1 n)
(cond ((= n 1)
(number->string (stream-car stream1)))
(else
(string-append
(number->string (stream-car stream1)) ", "
(print-first-n (stream-cdr stream1) (- n 1))))))
上述解决方案适用于 n
的小值,但对于大值来说效率非常低(将创建大量临时字符串,追加操作具有 O(n^2)
的复杂性)。为了更有效的实施,请考虑使用 SRFI-13 的连接程序,如下所示:
(require srfi/13)
(define (print-first-n stream1 n)
(let loop ((strm stream1) (n n) (acc '()))
(if (= n 1)
(string-concatenate-reverse
(cons (number->string (stream-car strm)) acc))
(loop (stream-cdr strm)
(sub1 n)
(list* ", " (number->string (stream-car strm)) acc)))))
无论哪种方式:假设 integers
是从 1
开始的无限整数流,它看起来是这样的:
(print-first-n integers 5)
=> "1, 2, 3, 4, 5"
如果流包含一些其他数据类型,请使用适当的过程将每个元素转换为字符串。
如果您的函数只是 打印 流内容,并且不需要构建字符串(如 Óscar 的回答),这是我的看法(使用 SRFI 41 流):
(define (print-first-n stream n)
(stream-for-each (lambda (delim item)
(display delim)
(display item))
(stream-cons "" (stream-constant ", "))
(stream-take n stream)))
示例:
> (define natural (stream-cons 1 (stream-map (lambda (x) (+ x 1)) natural)))
> (print-first-n natural 10)
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
要输出到字符串(如 Óscar 的回答),只需将整个内容包装在字符串端口中即可:
(define (print-first-n stream n)
(call-with-output-string
(lambda (out)
(stream-for-each (lambda (delim item)
(display delim out)
(display item out))
(stream-cons "" (stream-constant ", "))
(stream-take n stream)))))
我可以使用以下代码将 n 个数字打印为列表:
(define (print-first-n stream1 n)
(cond((= n 0) '())
(else(cons(stream-car stream1) (print-first-n (stream-cdr stream1) (- n 1))))))
但是我不知道如何添加逗号。
你不能在普通列表中打印逗号,但我们可以用流的内容构建一个字符串,用逗号分隔。这将起作用,假设字符串包含 numbers:
(define (print-first-n stream1 n)
(cond ((= n 1)
(number->string (stream-car stream1)))
(else
(string-append
(number->string (stream-car stream1)) ", "
(print-first-n (stream-cdr stream1) (- n 1))))))
上述解决方案适用于 n
的小值,但对于大值来说效率非常低(将创建大量临时字符串,追加操作具有 O(n^2)
的复杂性)。为了更有效的实施,请考虑使用 SRFI-13 的连接程序,如下所示:
(require srfi/13)
(define (print-first-n stream1 n)
(let loop ((strm stream1) (n n) (acc '()))
(if (= n 1)
(string-concatenate-reverse
(cons (number->string (stream-car strm)) acc))
(loop (stream-cdr strm)
(sub1 n)
(list* ", " (number->string (stream-car strm)) acc)))))
无论哪种方式:假设 integers
是从 1
开始的无限整数流,它看起来是这样的:
(print-first-n integers 5)
=> "1, 2, 3, 4, 5"
如果流包含一些其他数据类型,请使用适当的过程将每个元素转换为字符串。
如果您的函数只是 打印 流内容,并且不需要构建字符串(如 Óscar 的回答),这是我的看法(使用 SRFI 41 流):
(define (print-first-n stream n)
(stream-for-each (lambda (delim item)
(display delim)
(display item))
(stream-cons "" (stream-constant ", "))
(stream-take n stream)))
示例:
> (define natural (stream-cons 1 (stream-map (lambda (x) (+ x 1)) natural)))
> (print-first-n natural 10)
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
要输出到字符串(如 Óscar 的回答),只需将整个内容包装在字符串端口中即可:
(define (print-first-n stream n)
(call-with-output-string
(lambda (out)
(stream-for-each (lambda (delim item)
(display delim out)
(display item out))
(stream-cons "" (stream-constant ", "))
(stream-take n stream)))))