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

List 方案:打印列表的前n个元素,list,scheme,List,Scheme,首先,这并没有多大帮助,因为这个问题从来没有得到真正的回答,我也没有按照投稿人的建议去做。此外,我正在通过do循环来实现这一点,并且几乎实现了解决方案 我需要做一个过程,它将返回传递列表中的前n个项目。例如,(first-n4’(582940487))应该给出(58229) 以下是我的方法,显示屏用于确保循环正常工作,即: (define (front-n n list) (do ((i 0 (+ i 1))) ((> i (- n 1))) (display (lis

首先,这并没有多大帮助,因为这个问题从来没有得到真正的回答,我也没有按照投稿人的建议去做。此外,我正在通过do循环来实现这一点,并且几乎实现了解决方案

我需要做一个过程,它将返回传递列表中的前n个项目。例如,(first-n4’(582940487))应该给出(58229)

以下是我的方法,显示屏用于确保循环正常工作,即:

(define (front-n n list)
  (do ((i 0 (+ i 1)))
    ((> i (- n 1)))
    (display (list-ref list i))))
我如何让它返回一个列表,或者输出一个列表?

怎么样

(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)
>

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

如果输入列表中的项少于n项,则do循环和@Penguino的递归函数都会失败。以下是基于命名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)))))
命名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)))))

设置
不是特别有计划,但至少它与命名let版本共享一个属性,即它不构建中间堆栈。

这里是一个尾部递归版本:

(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)]))
(定义(以n为例)
(定义(iter计数器结果子列表)
(续)
[(空?子列表)结果]
[(
它与library过程略有不同,因为如果给定的take count大于列表的长度,则library过程将抛出错误,而在这种情况下,此函数将返回整个列表


但是请注意,它使用了append。我还没有找到解决这个问题的方法。

您的错误检查是一个非常糟糕的主意:每次检查都是O(n),每次递归调用一次,这意味着您的函数的运行时复杂性为O(n²)。去掉它,你的答案就可以了。我一直在寻找这样的东西,它帮了我很大的忙。谢谢。@Chris Jester Young-是的,经过深思熟虑,我同意错误检查。如果列表中的项少于n,则错误检查将失败。将第一项更改为
(或(null?list)(=0 n))
,当列表少于元素数时,错误检查不会失败。对于递归版本:如果
n
为零,您应该返回空列表。只有当您试图从中获取的列表也是空的(
,而不是
)时,返回该列表才是正确的;如果n为零,
(list)
返回空列表。啊,不管怎样,我想你用一些变量隐藏了
list
。通常,您宁愿编写
”()
或将
nil
定义为空列表,而不是编写
(列表)
。我误读了密码。个人怪癖。我通常写
(列表)
,而不是
”()
。不知道为什么,或者我什么时候开始的。可能是