Scheme 一次展平程序
我在编写一个将列表展平一次的过程时遇到了一些困难,即Scheme 一次展平程序,scheme,lisp,racket,Scheme,Lisp,Racket,我在编写一个将列表展平一次的过程时遇到了一些困难,即 (展平一次’((b)(cf)(d)(e))将产生(bcf(d)(e))。我查阅了一些关于标准展平过程工作原理的资料,但它实现了我必须使用的中级学生lambda语言表单中未包含的功能。据我所知,一个foldr会有所帮助,并且已经成功地做到了这一点 (define (flatten-once lst) (cond [(empty? lst) lst] [else ((foldr cons (first (rest lst
(展平一次’((b)(cf)(d)(e))
将产生(bcf(d)(e))
。我查阅了一些关于标准展平过程工作原理的资料,但它实现了我必须使用的中级学生lambda
语言表单中未包含的功能。据我所知,一个foldr
会有所帮助,并且已经成功地做到了这一点
(define (flatten-once lst)
(cond
[(empty? lst) lst]
[else
((foldr cons (first (rest lst)) (first lst)))]))
它返回
”(bcf)
,所以我猜它会使列表的一部分变平。我尝试通过递归继续定义,但这只会产生错误,所以我想我遗漏了一些东西。建议的代码过于复杂,请抵制到处使用折叠的诱惑,它们不是所有问题的答案-我这么说是因为我经常看到您的其他问题,对foldr
或foldl
有一个不必要的调用。一个简单的append
就可以做到:
(define (flatten-once lst)
(apply append lst))
它按预期工作:
(flatten-once '((b) (c f) ((d)(e))))
=> '(b c f (d) (e))
如果输入列表包含非列表的元素,则需要做更多的工作。要特别小心,我们可以这样做:
(define (flatten-once lst)
(apply append
(map (lambda (e) (if (cons? e) e (list e)))
lst)))
现在,它将适用于这样的输入,注意元素a
已添加到列表中。另一种选择是将其从列表中删除,如果这更有意义,则将上述代码中的(列表e)
替换为”()
(flatten-once '(a (b) (c f) ((d)(e))))
=> '(a b c f (d) (e))
最后,根据@Alex回答的精神,第二个变体也可以使用foldr
编写:
(define (flatten-once lst)
(foldr (lambda (e acc)
(append (if (cons? e) e (list e)) acc))
'()
lst))
建议的代码过于复杂,请抵制到处使用折叠的诱惑,它们不是所有问题的答案-我这样说是因为我看到了您的其他问题,而且经常会有不必要的调用
foldr
或foldl
。一个简单的append
就可以做到:
(define (flatten-once lst)
(apply append lst))
它按预期工作:
(flatten-once '((b) (c f) ((d)(e))))
=> '(b c f (d) (e))
如果输入列表包含非列表的元素,则需要做更多的工作。要特别小心,我们可以这样做:
(define (flatten-once lst)
(apply append
(map (lambda (e) (if (cons? e) e (list e)))
lst)))
现在,它将适用于这样的输入,注意元素a
已添加到列表中。另一种选择是将其从列表中删除,如果这更有意义,则将上述代码中的(列表e)
替换为”()
(flatten-once '(a (b) (c f) ((d)(e))))
=> '(a b c f (d) (e))
最后,根据@Alex回答的精神,第二个变体也可以使用foldr
编写:
(define (flatten-once lst)
(foldr (lambda (e acc)
(append (if (cons? e) e (list e)) acc))
'()
lst))
正如奥斯卡·洛佩斯(Oscar López)已经说过的,诀窍是使用
附加
如果要将解决方案与foldr
一起使用:
(define (flatten-once lst)
(foldr append '() lst))
它应该像预期的那样工作。诀窍正如奥斯卡·洛佩斯所说的,使用附加
如果要将解决方案与foldr
一起使用:
(define (flatten-once lst)
(foldr append '() lst))
它应该可以像预期的那样工作。没有奥斯卡版本那么优雅,但是没有添加附件(在我的测试中速度是后者的两倍):
NB在使用lambda语言的中级学生中
这需要表示为:
(define (flatten-once-helper lst first res)
(if (null? lst)
res
(let ((e (car lst)))
(flatten-once-helper
(cdr lst)
first
(if (and first (cons? e))
(flatten-once-helper e #f res)
(cons e res))))))
(define (flatten-once lst)
(reverse (flatten-once-helper lst #t null)))
没有奥斯卡的版本那么优雅,但是没有添加附加(在我的测试中速度是奥斯卡的两倍):
NB在使用lambda语言的中级学生中
这需要表示为:
(define (flatten-once-helper lst first res)
(if (null? lst)
res
(let ((e (car lst)))
(flatten-once-helper
(cdr lst)
first
(if (and first (cons? e))
(flatten-once-helper e #f res)
(cons e res))))))
(define (flatten-once lst)
(reverse (flatten-once-helper lst #t null)))
那么(展平一次(a(b)(c f)((d)(e)))
?@uselpa不知道输入是否可以包含非列表,但为了安全起见,我更新了我的答案。谢谢你指出这一点<代码>配对?
未在中级学生中定义,且具有lambda
无需复制(列表e)
具有附加
;折叠功能可以等效为(lambda(e acc)(if(cons?e)(append e acc)(cons e acc))
@JoshuaTaylor无需。你不能附加非列表,所以如果存在非列表,它应该会失败,IMHO。那么(展平一次)(a(b)(c f)((d)(e)))
?@uselpa输入是否可以包含非列表是未知的,但为了安全起见,我更新了我的答案。谢谢你指出这一点<代码>配对?
未在中级学生中定义,且具有lambda
无需复制(列表e)
具有附加
;折叠功能可以等效为(lambda(e acc)(if(cons?e)(append e acc)(cons e acc))
@JoshuaTaylor无需。你不能附加一个非列表,所以如果存在非列表,它应该会失败,IMHO。虽然它对于你的学校作业和中级学生语言是N/a,但在“真实的”Racket中“展平一级”是。虽然对于你的学校作业和中级学生语言是N/a,但是在“真实的”Racket中“展平一级”是。那么(展平一次’(a(b)(cf)((d)(e)))
?@uselpa另一个地方,如果Scheme/Racket的fold[lr]
函数像Common Lisp的reduce那样使用键
参数,那会更好;它应该是(reduce'append lst:key'到列表中)
:\@JoshuaTaylor列表的是什么?这里值得注意的是,使用正确的关联折叠非常重要。对于列表(wxyz)
,它相当于(追加w(追加x(追加y(追加z’(!))))
,只复制足够的长度(结果的长度)并且应该以线性时间运行。左关联折叠应该是(append(append(append(append w’())x)y)z)
和将分配大量额外内存,并以二次时间运行。@uselpa有没有比append
更快的方法来获取两个列表x
和y
,并创建一个以x
元素开始并以y
作为尾部的新列表?除非OP希望以破坏性方式执行此操作,否则所有这些在顶级列表旁边需要复制(除了最后一个),这正是append
所做的。那么(展平一次(a(b)(cf)((d)(e))
?@uselpa另一个地方,如果Scheme/Racket的fold[lr]
函数像Com一样使用键参数会更好吗