You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

LISP使用append时保留元素括号及实现grouper函数的问题咨询

解决LISP中使用append时保留元素括号的问题

首先,咱们来拆解下你代码里括号消失的原因:

你当前的代码中,初始化的l(list (car l1) (car l2)),得到的是(1 4)——这是一个扁平列表,而非包含子列表的嵌套结构。之后每次循环里的(append l (list (car l1) (car l2))),是把(2 5)(3 6)这类扁平列表直接拼接到l后面,append的作用就是合并两个列表的元素,自然就会得到(1 4 2 5 3 6)这种完全扁平的结果,而非你想要的嵌套结构。

要实现((1 4)(2 5)(3 6))的效果,核心是把每一对元素先包裹成子列表,再将这些子列表收集起来组成最终的嵌套列表。下面给你两种解决方案:

方案一:使用Loop的Collect子句(推荐)

这是LISP中处理这类列表收集任务最惯用的写法,代码简洁且可读性高:

(defun grouper (l1 l2)
  (loop
    while (and l1 l2)  ; 只要两个列表都还有元素就继续循环
    collect (list (car l1) (car l2))  ; 把当前一对元素包装成子列表,收集到结果中
    do (setq l1 (cdr l1)
             l2 (cdr l2))))  ; 移动两个列表的指针

测试示例:

(grouper '(1 2 3) '(4 5 6)) ; 返回 ((1 4) (2 5) (3 6))

方案二:修改你原有的代码

如果想基于你原来的代码调整,需要改变初始化和append的逻辑,确保每次添加的是子列表而非子列表的元素:

(defun grouper1 (l1 l2) 
  ;; 初始化时,先把第一对元素包装成子列表,再放到外层列表里
  (setq l (list (list (car l1) (car l2))))
  (loop
    (setq l1 (cdr l1))
    ;; 直接判断l1是否为空,比判断(car l1)更稳妥(避免列表包含nil元素的情况)
    (when (null l1) (return l))
    (setq l2 (cdr l2))
    ;; 把新的子列表放到一个列表中,再用append添加到结果里
    (setq l (append l (list (list (car l1) (car l2)))))
  )
)

这个版本也能得到预期结果,但要注意:手动使用append的效率较低,因为每次append都需要遍历整个现有列表,当列表较长时性能会受影响,所以更推荐第一种方案。

内容的提问来源于stack exchange,提问作者Ziyin Zeng

火山引擎 最新活动