如何用Lisp实现将字符串按空格分割,非空格字符嵌套为子列表?
字符串转嵌套列表的Lisp实现思路
需求说明
将字符串转换为嵌套列表:
- 以空格为分隔符
- 连续的非空格字符存入单独的子列表
- 空格字符直接作为外层列表的元素
期望输出示例:((#\w #\o #\r #\d) #\Space (#\w #\o #\r #\d))
现有代码问题
你最初实现的函数仅能生成扁平化列表:
(defun string->list (str) "Take a string, split it into chars and add it into a list." (let ((list-string '())) (loop for x from 0 to (- (length str) 1) do (push (char str x) list-string)) (nreverse list-string)))
输出结果:(#\w #\o #\r #\d #\Space #\w #\o #\r #\d)
修改后的函数逻辑未做实质调整,依然输出扁平化结果:
(defun string->list (str) (let ((list-string '())) (loop for letter from 0 to (- (length str) 1) if (equal (char str letter) #\Space) do (push (char str letter) list-string) else do (push (char str letter) list-string)) (nreverse list-string)))
解决思路指引
新增临时子列表变量
不能仅维护一个外层列表,需要额外定义一个变量(比如current-word),用来暂存当前正在收集的非空格字符子列表,初始值设为空列表。分分支处理字符
- 遇到非空格字符:将字符加入
current-word; - 遇到空格字符:
- 若
current-word不为空,先将这个子列表反转后加入外层列表(因为push会反转顺序),再清空current-word; - 直接将空格字符加入外层列表。
- 若
- 遇到非空格字符:将字符加入
处理循环收尾
遍历完所有字符后,检查current-word是否还有未存入外层列表的字符(比如字符串末尾无空格的情况),如果有,将其反转后加入外层列表。修正列表顺序
最后对整个外层列表执行nreverse,修正因push操作导致的顺序反转问题。
示例实现
按照上述思路,完整实现代码如下:
(defun string->nested-list (str) (let ((outer-list '()) (current-word '())) (loop for char across str do (cond ((char= char #\Space) (when current-word (push (nreverse current-word) outer-list) (setf current-word '())) (push char outer-list)) (t (push char current-word)))) ;; 处理字符串末尾的非空格子列表 (when current-word (push (nreverse current-word) outer-list)) (nreverse outer-list)))
测试调用:(string->nested-list "word word"),会输出期望的((#\w #\o #\r #\d) #\Space (#\w #\o #\r #\d))
内容的提问来源于stack exchange,提问作者belaja-akacija
相关产品推荐
相关产品推荐

