繁体   English   中英

方案:打印出列表的前n个元素

[英]Scheme: Printing out first n elements of list

首先, 计划:返回仅包含lst的第一个元素的lst并没有多大帮助,因为从未真正回答过该问题,因此我遵循了贡献者的建议,但没有成功。 此外,我正在通过do循环来解决这个问题,并且几乎已经实现了解决方案。

我需要执行一个过程,该过程将返回传递的列表中的前n个项目。 例如,(first-n 4'(5 8 2 9 4 0 8 7))应该给出(5 8 2 9)。

这是我的方法,此处显示的内容可确保循环正常运行,即:

(define (front-n n list)
  (do ((i 0 (+ i 1)))
    ((> i (- n 1)))
    (display (list-ref list i))))

我该如何使返回列表或输出列表?

如果输入列表中的项少于n个,则do循环和@Penguino的递归函数都将失败。 这是一个基于named-let的简单版本,重命名take是此函数的常规名称:

(define (take n xs)
  (let loop ((n n) (xs xs) (zs (list)))
    (if (or (zero? n) (null? xs))
        (reverse zs)
        (loop (- n 1) (cdr xs)
              (cons (car xs) zs)))))

或者,如果您喜欢递归函数版本:

(define (take n xs)
  (if (or (zero? n) (null? xs))
      (list)
      (cons (car xs) (take (- n 1) (cdr xs)))))

named-let版本比递归版本更可取,因为递归不在尾部,因此它构建了一个大的中间堆栈。

您说过想要使用do的版本。 这更难,因为终止循环的测试是在循环操作之后执行的,并且您需要在操作之前执行测试。 您可以笨拙地进行单次测试,也可以使用以下循环将操作延迟到测试成功之后:

(define (take n xs)
  (let ((zs (list)))
    (do ((n n (- n 1)) (xs xs (cdr xs)))
        ((or (zero? n) (null? xs)) (reverse zs))
      (set! zs (cons (car xs) zs)))))

set! 并不是特别有计划的,但是至少它与named-let版本共享不构建中间堆栈的属性。

怎么样

(define (front-n n list)
  (cond ((= 0 n) '())
        (else (cons (car list) (front-n (- n 1) (cdr list))))))

并添加了一些伪错误陷阱。 测试:

(front-n 4 '(5 8 2 9 4 0 8 7))
(front-n 8 '(5 8 2 9 4 0 8 7))

产生预期的输出:

'(5 8 2 9)
'(5 8 2 9 4 0 8 7)
>

请注意,错误检查可能很有用。

这是尾递归版本:

(define (take n a-list)
  (define (iter counter result sublist)
    (cond
      [(empty? sublist) result]
      [(< counter n)
       (iter
         (+ counter 1)
         (append result (list (car sublist)))
         (cdr sublist))]
      [else result]))
  (cond
    [(= n 0) '()]
    [else (iter 0 '() a-list)]))

它与库过程略有不同,因为如果给出的盘点计数大于列表的长度,则库过程将引发错误,而在这种情况下,此函数将返回整个列表。

但是请注意,它利用了附加。 我还没办法解决。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM