List 用于反转列表的Scheme函数
对于我的编程语言类,我应该在Scheme中编写一个函数来反转列表,而不使用预先制作的反转函数。到目前为止,我得到的是List 用于反转列表的Scheme函数,list,scheme,reverse,List,Scheme,Reverse,对于我的编程语言类,我应该在Scheme中编写一个函数来反转列表,而不使用预先制作的反转函数。到目前为止,我得到的是 (define (reverseList lst) (COND ((NULL? lst) '()) (ELSE (CONS (reverseList(CDR lst)) (CAR lst))) )) 我遇到的问题是,如果我输入一个列表,比如说(abc),它会给我((().c.b).a) 如果没有多组括号和我怎么才能得到一个干净的列表呢?您的实现的问题是cons没有接收列表作为其
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (CONS (reverseList(CDR lst)) (CAR lst)))
))
我遇到的问题是,如果我输入一个列表,比如说(abc)
,它会给我((().c.b).a)
如果没有多组括号和
我怎么才能得到一个干净的列表呢?您的实现的问题是cons
没有接收列表作为其第二个参数,因此您构建的答案不是一个正确的列表,记住:正确的列表是通过cons
ing一个元素与一个列表来构造的,最后一个列表是空的
一种可能的解决方法是使用辅助函数,在累加器参数中构建答案,cons
将元素反向排列-顺便说一句,此解决方案是尾部递归的:
(define (reverse lst)
(reverse-helper lst '()))
(define (reverse-helper lst acc)
(if (null? lst)
acc
(reverse-helper (cdr lst) (cons (car lst) acc))))
(reverse '(1 2 3 4 5))
=> '(5 4 3 2 1)
你已经走到一半了。结果中元素的顺序是正确的,只有结构需要修复 您需要执行此转换:
(((() . c) . b) . a) ; input
--------------------
(((() . c) . b) . a) () ; trans-
((() . c) . b) (a) ; for-
(() . c) (b a) ; mation
() (c b a) ; steps
--------------------
(c b a) ; result
这很容易编码。我们可以立即获得中间值的car
和cdr
。在每一步中,下一个中间结果由(cons(cdr中间值)中间结果)
构造,而中间结果
启动为空列表,因为这是我们在这里构造的-列表:
中间结果
用作累加器。这就是所谓的“累加器技术”<代码>步骤表示使用“命名let”语法编码的循环步骤
因此,总体上相反
(define (my-reverse lst)
(transform-rev
(reverseList lst)))
您能否调整
transformrev
,使其能够接受原始列表作为输入,从而跳过reverseList
调用?您只需要更改数据访问部分,即如何获得下一个临时值,以及向临时结果中添加的内容 逐步浏览列表,并将列表的car追加到递归调用中
(define (my-reverse L)
(fold cons '() L)) ;;left fold
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (APPEND (reverseList(CDR lst)) (LIST (CAR lst))))
))
你明白每个
的意思吗?为什么会看到这么多括号?这里的答案将为你指出一个正确的解决方案,Willence的解决方案涵盖了你所看到的,但你也可能从中受益,并且。您可能也会发现这很有用。请更改算法。您的算法是在反向列表的头部插入一个空列表。它一直这样做是为了部分反转。我想你的意思是把列表连接起来,这样你就得到了一个平面列表,作为一个列表列表的结果。。。名单的一部分。使用append而不是consum你能详细说明你的答案吗?这被标记为低质量。@CodeMaverick折叠以初始值(”()
开始,然后使用给定函数(cons
在这种情况下)为列表中的每个项目更新该值(在左折叠的情况下从左到右)。由于cons
从右到左构建列表,并且由于输入元素从左到右来自传入列表(由于左折叠),因此生成的列表与原始列表相反。类似地,您可以使用右折叠来复制列表,右折叠从右到左获取输入元素。使用append
来构建列表有点不受欢迎,这意味着您没有以正确的方式重复出现。此外,这是可怕的效率低下,想想看。大多数时候你想使用cons和tail递归来建立一个列表,请看我的答案。这是一篇非常有趣的文章。我想我是众多有基本缺陷的毕业生之一:-)谢谢。助手功能有什么原因或好处吗?在我看来,您可以将其代码放入原始函数中,[将acc替换为“()”,这样一切都可以正常工作?我将其作为助手编写,因为原始函数只接收一个参数,但我们需要两个参数来实现尾部递归。通常我会将其编写为命名的let
,以避免创建两个函数,但这可能更难理解,因为OPin lisp append不是低效的,您不是在移动数据,只是在设置指针。不管奥斯卡·洛佩兹说什么。该算法是正确的,所以它是正确的。反向帮助程序
的更好名称是,因为该函数在SRFI 1中被调用,它看起来不像是人工帮助程序,更像是真实的函数。:-)
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (APPEND (reverseList(CDR lst)) (LIST (CAR lst))))
))