我在 lisp 格式功能方面遇到了一些麻烦。我有以下清单:
((X X X)(X X X X X X)(X X X X X X X X X))
Run Code Online (Sandbox Code Playgroud)
我需要按以下格式打印它:
X X X
XX XX XX
XXXXXXXXX
Run Code Online (Sandbox Code Playgroud)
关于如何实现这一目标的任何想法?format 函数有点令人困惑,HyperSpec 文档似乎对我没有任何帮助。谢谢。
就像每个工具format
都有其局限性一样,它不太适合此类问题。可能您可以使用纯格式获得的最好的结果,而无需借助~?
or的黑魔法~/
,您或任何其他人将来可能不会理解,以下代码是:
CL-USER> (format t "~{~{~A ~}~%~}"
'((X X X) (X X X X X X) (X X X X X X X X X)))
X X X
X X X X X X
X X X X X X X X X
Run Code Online (Sandbox Code Playgroud)
如果您想获得复杂的输出结构,请尝试进行一些预处理。就像,如果列表的格式是硬编码的,您可以使用:
(format t "~{~{~6A~} ~%~}"
(mapcar (lambda (l)
(loop :for i :from 0 :to (1- (length l)) :by (/ (length l) 3)
:collect (format nil "~{~A ~}"
(subseq l i (+ i (/ (length l) 3))))))
'((X X X) (X X X X X X) (X X X X X X X X X))))
Run Code Online (Sandbox Code Playgroud)
这里我们首先将列表中的项目收集到每个列表中相同数量的组中,打印它们,这样就得到了 3 个具有相同元素数量的列表,然后可以通过 进行处理format
。
format
您可以在 Peter Seibel 的优秀 Lisp 书籍的相应章节中找到更多信息: http://gigamonkeys.com/book/a-few-format-recipes.html
编辑
如果您有可变数量的列表,并且每个列表都比前一个大两倍,则还需要事先准备格式字符串:
CL-USER> (defun format-custom-list (list)
(format t (format nil "~~{~~{~~~DA~~} ~~%~~}" (* 2 (length list)))
(mapcar (lambda (l)
(let* ((len (length l))
(len/3 (/ len 3)))
(loop :for i :from 0 :to (1- len) :by len/3
:collect (format nil "~{~A ~}"
(subseq l i (+ i len/3))))))
list)))
CL-USER> (format-custom-list '((X X X) (X X X X X X) (X X X X X X X X X)
(X X X X X X X X X X X X)))
X X X
X X X X X X
X X X X X X X X X
X X X X X X X X X X X X
NIL
Run Code Online (Sandbox Code Playgroud)
(尾部nil
是 的输出format
,它不会打印到输出流t
。如果您想从此函数中获取字符串,请使用nil
asformat
的输出流。)