我想将元素b
附加到列表a
(让我们说(a1, a2, ... an)
),例如将号码3
追加到(1 2)
会产生(1 2 3)
到目前为止,我一直在做
(append a (list b))
,有点长而不优雅,所以我想知道是否有“更好”的方式...
答案 0 :(得分:3)
您是否一次性构建一个列表,一个项目?如果是这样,执行此操作的惯用方法是使用cons
向后构建列表,然后使用reversing
最终结果:
(define (map-using-cons-and-reverse f lst)
(let loop ((result '())
(rest lst))
(if (null? rest)
(reverse result)
(loop (cons (f (car rest)) (cdr rest))))))
或者,如果您的列表构建符合“右向折叠”递归方法,那也是惯用的:
(define (map-using-recursion f lst)
(let recur ((rest lst))
(if (null? rest)
'()
(cons (f (car rest)) (recur (cdr rest))))))
以上代码片段仅用于说明在一般情况下采用的解决方案方法;对于可以使用折叠直接实现的内容,例如map
,使用fold更具惯用性:
(define (map-using-cons-and-reverse f lst)
(reverse (foldl (lambda (item result)
(cons (f item) result))
'() lst)))
(define (map-using-recursion f lst)
(foldr (lambda (item result)
(cons (f item) result))
'() lst))
答案 1 :(得分:2)
你有多频繁追加到最后?
如果你想要做很多事情(而不是在前面),那么你做错了。正确的方法是翻转事物:认为cons
把事情放在后面,first
检索最后一个元素,rest
检索除了最后的所有内容,等等。然后,你可以使用列表通常
但是,如果你想把事情放在列表的末尾,以便把事情放在前面,那么这是你用一个列表做的最好的事情。你可以编写一个函数来包装你认为“不优雅”的东西。传统上它被称为snoc
(向后cons
)
(define (snoc lst e) (append lst (list e)))
或者如果您更喜欢自己实施整个事情:
(define (snoc lst e)
(cond
[(empty? lst) (list e)]
[(cons? lst) (cons (first lst) (snoc (rest lst) e))]))
请注意,这两种方法具有相同的时间复杂度:O(n)
其中n
是列表的长度。
但是如果你希望它有效,你可以使用一种称为双端队列的数据结构,这种效率非常高效(每次操作的时间恒定)。有关详细信息,请参阅http://www.westpoint.edu/eecs/SiteAssets/SitePages/Faculty%20Publication%20Documents/Okasaki/jfp95queue.pdf。