List 方案:打印列表的前n个元素
首先,这并没有多大帮助,因为这个问题从来没有得到真正的回答,我也没有按照投稿人的建议去做。此外,我正在通过do循环来实现这一点,并且几乎实现了解决方案 我需要做一个过程,它将返回传递列表中的前n个项目。例如,(first-n4’(582940487))应该给出(58229) 以下是我的方法,显示屏用于确保循环正常工作,即: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
(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
定义为空列表,而不是编写(列表)
。我误读了密码。个人怪癖。我通常写(列表)
,而不是”()
。不知道为什么,或者我什么时候开始的。可能是