固定宽度字段中的漂亮打印值

时间:2014-11-12 18:40:08

标签: format lisp common-lisp multidimensional-array

我想在固定宽度字段中打印由列名和值组成的矩阵。这是我写的代码:

(defstruct
  (matrix
    (:print-function (lambda (my-matrix stream depth)
                     (declare (ignore depth))
                     (let* ((dimensions (matrix-dimensions my-matrix))
                            (column-names (matrix-column-names my-matrix))
                            (values (matrix-values my-matrix))
                            (number-of-rows (nth 0 dimensions))
                            (number-of-columns (nth 1 dimensions)))
                       (progn (loop :for i :upto number-of-columns
                                 :do (if (< i number-of-columns)
                                         (format stream (nth i column-names))
                                         (format stream "~%")))
                              (loop :for j :upto (1- number-of-rows)
                                 :do (loop :for k :upto number-of-columns
                                        :do (if (< k number-of-columns)
                                                (format stream (write-to-string (aref values j k)))
                                                (format stream "~%")))))))))
  dimensions
  column-names
  values)

但是,如果我运行此代码,这就是我得到的:

CL-USER> (make-matrix :dimensions '(3 2)
                  :column-names '("Michael" "Alexandra")
                  :values (make-array '(3 2) :initial-contents '((54 34) (65 78) (49 38))))
MichaelAlexandra
5434
6578
4938

如何编辑我的:print-function(更具体地说是它的格式部分),以便在固定宽度的字段中整齐地打印列名和值?

我读到为了这个目的,格式中存在一个~w指令,但并没有真正理解它是如何工作的。

2 个答案:

答案 0 :(得分:3)

"~NN"指令中使用format

(defstruct
  (matrix
    (:print-function (lambda (my-matrix stream depth)
                       (declare (ignore depth))
                       (let* ((dimensions (matrix-dimensions my-matrix))
                              (column-names (matrix-column-names my-matrix))
                              (values (matrix-values my-matrix))
                              (number-of-rows (nth 0 dimensions))
                              (number-of-columns (nth 1 dimensions)))
                         (loop :for i :upto number-of-columns
                           :do (if (< i number-of-columns)
                                   (format stream "~10s" (nth i column-names))
                                   (terpri stream)))
                         (loop :for j :upto (1- number-of-rows)
                           :do (loop :for k :upto number-of-columns
                                 :do (if (< k number-of-columns)
                                         (format stream "~10s" (aref values j k))
                                         (terpri stream))))))))
  dimensions
  column-names
  values)

PS。 progn

中不需要let

答案 1 :(得分:0)

我会用CLOS,Common Lisp Object System编写它。

具有三个initargs的矩阵类:

(defclass matrix ()
  ((dimensions   :initarg :dimensions)
   (column-names :initarg :column-names)
   (values       :initarg :values)))

print-matrix方法:

(defmethod print-matrix ((matrix matrix) &optional (stream *standard-output*))
  (with-slots (dimensions column-names values)
      matrix
    (destructuring-bind (number-of-rows number-of-columns)
        dimensions
      (dotimes (i number-of-columns)
        (format stream "~10a" (nth i column-names)))
      (terpri stream)
      (dotimes (j number-of-rows)
        (dotimes (k number-of-columns)
          (format stream "~10s" (aref values j k)))
        (terpri stream)))))

试一试:

? (print-matrix (make-instance 'matrix
                  :dimensions '(3 2)
                  :column-names '("Michael" "Alexandra")
                  :values (make-array '(3 2)
                            :initial-contents '((54 34) (65 78) (49 38)))))
Michael   Alexandra 
54        34        
65        78        
49        38        

更改班级的默认打印机:

(defmethod print-object ((matrix matrix) stream)
  (print-matrix matrix stream))