List 方案双重复列表备选方案

List 方案双重复列表备选方案,list,scheme,duplicates,double,List,Scheme,Duplicates,Double,在我正在参加的一个实践考试中,有一个问题要求创建一个过程,该过程采用一个列表,并创建一个新列表,该列表包含旧列表中每个元素的两个,同时保留顺序。他们提供的例子如下: (double-duplicate (list 1 2 3 4 4 5)) 产生 (1 1 2 2 3 3 4 4 4 4 5 5) 我设法找到了一个使用map和Flatte的解决方案: (define (flatten list) (cond ((null? list) '())

在我正在参加的一个实践考试中,有一个问题要求创建一个过程,该过程采用一个列表,并创建一个新列表,该列表包含旧列表中每个元素的两个,同时保留顺序。他们提供的例子如下:

    (double-duplicate (list 1 2 3 4 4 5))
产生

    (1 1 2 2 3 3 4 4 4 4 5 5)
我设法找到了一个使用map和Flatte的解决方案:

    (define (flatten list)
       (cond ((null? list) '())
             ((list? (car list)) (append (flatten (car list)) (flatten (cdr list))))
             (else (cons (car list) (flatten (cdr list))))))

    (define (double-duplicate ls)
      (define (helper list1 list2)
        (flatten (map list list1 list2)))
      (helper ls ls))
虽然它确实有效,但我并不认为它是最有效的解决方案,因为我使用的是带有3个参数的映射形式,我不喜欢为了去掉多余的括号而不得不编写第二个过程(展平)的想法。有人能想出更好的方法吗?我有点不知道还能怎么写。我很欣赏你的想法


*注意:我使用麻省理工学院的方案来完成所有这一切。

你使用的是球拍吗?如果是这样,您可以使用
附加映射

(define (double-duplicate lst)
  (append-map (lambda (x) (list x x)) lst))
append map
类似于Scala的
flatmap

如果需要,编写自己版本的
append map
并不难:

(define (append-map func lst)
  (fold-right (lambda (e r)
                (append (func e) r)) '() lst))

这一个更适合于
累积

(define (double-duplicate lst)
  (accumulate (lambda (e acc)
                (cons e (cons e acc)))
              '()
              lst))

同样,假设
acculate
的定义与您前面的问题相同,即,作为向右折叠。

但是显然,append map仍然有效。甚至不需要定义它。不过,还是要感谢你给出了定义。我喜欢看这些函数是如何工作的。事实上,它也是以同样的方式使用累积的!我更喜欢您的过程而不是我的过程,尽管我个人会将lambda作为辅助函数编写。快速提问:当你说累积被定义为向右折叠时,你的确切意思是什么?我对编程中的术语“fold”不太熟悉
fold
accumulate
是一种使用列表处理每个元素的过程。它可以返回按从左到右的顺序(折叠右键)或从右到左的顺序(折叠左键)处理的列表。查看具体细节,我会说从右/左折叠更准确。如果你想象一张你正在折叠的纸,右折从右向左折叠,左折从左向右折叠。谢谢克里斯。我感谢你的意见