压扁一次程序

Nik*_*nov 1 lisp scheme racket

我正在努力编写一个程序,这个程序(flatten-once '((b) (c f) ((d)(e))))会使列表变平一次,即 产生'(b c f (d) (e))).我查看了几个关于标准flatten过程如何工作的来源,但它实现了intermediate student with lambda我需要使用的语言形式中未包含的函数.据我所知,它foldr会有所帮助,并设法得到这个

(define (flatten-once lst)
  (cond
   [(empty? lst) lst]
   [else 
    ((foldr cons (first (rest lst)) (first lst)))]))
Run Code Online (Sandbox Code Playgroud)

返回'(b c f),所以我想它会使列表的一部分变平.我尝试通过递归继续定义,但这只是错误,所以我想我错过了一些东西.

Ósc*_*pez 7

拟议的代码过于复杂,抵制在任何地方使用折叠的诱惑,它们不是所有东西的答案 - 我这样说是因为我已经看到了你的其他问题而且经常会有一个不必要的调用foldr或者foldl.一个简单的方法append就是诀窍:

(define (flatten-once lst)
  (apply append lst))
Run Code Online (Sandbox Code Playgroud)

它按预期工作:

(flatten-once '((b) (c f) ((d)(e))))
=> '(b c f (d) (e))
Run Code Online (Sandbox Code Playgroud)

如果输入列表包含非列表的元素,则需要完成更多工作.要非常小心,我们可以这样做:

(define (flatten-once lst)
  (apply append
         (map (lambda (e) (if (cons? e) e (list e)))
              lst)))
Run Code Online (Sandbox Code Playgroud)

现在它适用于这样的输入,注意到该元素a已添加到列表中.另一种办法是删除从列表中,如果让更多的意义则替换(list e)'()上面的代码.

(flatten-once '(a (b) (c f) ((d)(e))))
=> '(a b c f (d) (e))
Run Code Online (Sandbox Code Playgroud)

最后,本着@Alex的回答,第二个变体也可以用以下方法编写foldr:

(define (flatten-once lst)
  (foldr (lambda (e acc)
           (append (if (cons? e) e (list e)) acc))
         '()
         lst))
Run Code Online (Sandbox Code Playgroud)