能否使用map函数实现Lisp列表的线性化?
用Map相关函数实现Lisp列表扁平化当然可以!
先聊聊你当前实现的问题:你的f1遇到原子直接返回原子,f2用mapcar调用f1处理列表元素——但mapcar只会把每个元素的处理结果按原结构打包成新列表,不会把嵌套的结果展开拼接。比如处理(3 (4 5) 6)时,mapcar 'f1会得到(3 (4 5) 6),而不是展开后的(3 4 5 6),所以最终结果还是嵌套的。
要实现扁平化,核心是把每个子元素的扁平化结果拼接起来,这时候mapcan(或者mapcon)就派上用场了——它会将每个元素的处理结果(必须是列表)用nconc拼接成一个整体列表。
修正后的实现如下:
(defun flatten (x) (cond ((atom x) (list x)) ; 把原子转成单元素列表,方便后续拼接 (t (mapcan #'flatten x)))) ; mapcar+拼接,直接得到扁平化列表
测试一下:
(flatten '(1 2 (3 (4 5) 6))) ; 输出:(1 2 3 4 5 6)
简单解释下逻辑:
- 当输入是原子时,返回包含该原子的单元素列表(这样才能和其他列表拼接)
- 当输入是列表时,用
mapcan递归处理每个元素,每个元素的扁平化结果会被自动拼接成一个大列表,自然就消除了嵌套结构。
如果你坚持想用mapcar,也可以配合apply和append(不过效率不如mapcan,因为append会创建新列表):
(defun flatten-with-mapcar (x) (cond ((atom x) (list x)) (t (apply #'append (mapcar #'flatten-with-mapcar x)))))
这个版本里,mapcar先得到每个元素的扁平化子列表,再用apply append把所有子列表拼接起来,同样能得到结果。
内容的提问来源于stack exchange,提问作者mikha koltjia
相关产品推荐
相关产品推荐

