format - Help with printing a table

Deadly 提交于 2019-12-10 13:38:12

问题


This question will probably end in a facepalm, but I've tried for a while and am still stuck despite reading through the hyperspec.

Basically what I want to do is something like

(format t "~{|~{ ~5d~}|~%~}" '((1 23 2 312) (23 456 1 7890)))

but instead of hard-coding the 5 it should be calculated from the list (length of longest element from any nested list + 1) to give something like

|    1    23     2   312|
|   23   456     1  7890|      

Maybe I'm thinking way too complicated here and there is an easier way to do what I want, but I think I ran myself into a mental corner that I can't get out of.


回答1:


Assuming the required width is bound to width, then you can do this:

(format t "~{|~{ ~Vd~}|~%~}" width '((1 23 2 312) (23 456 1 7890)))

5 has been replaced by V and width has been added as an argument to FORMAT/

edit: original answer did not correctly account for the nested directives

In a format control string V may be used in place of any constant value, indicating that the corresponding value is to be taken from the argument list instead.

You can try this:

(setf width 5)
(setf data '((1 23 2 312) (23 456 1 7890)))

(format t "~{|~{ ~{~Vd~}~}|~%~}"
  (mapcar #'(lambda (r) (mapcar #'(lambda (v) (list width v)) r)) data) )

This format string requires the desired width to precede each value. The (mapcar ...) expression accomplishes this.




回答2:


I think that you have two options: let the format magic go and use other looping constructs or generate the format string itself:

(defun facepalm-printer (lol)
  (format t (format nil "~~{|~~{ ~~~ad~~}|~~%~~}"
                    (longest-member lol))
          lol))

The definition of longest-member is left as an exercise to the reader.



来源:https://stackoverflow.com/questions/4618503/format-help-with-printing-a-table

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!