2011-01-06 26 views
6

Esta pregunta probablemente terminará en una facepalm, pero lo he intentado por un tiempo y todavía estoy atascado a pesar de leer a través del hiperespec.- Ayuda con la impresión de una tabla

Básicamente lo que quiero hacer es algo así como

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

pero en vez de duro-codificante 5 debe calcularse a partir de la lista (longitud del elemento más largo de cualquier lista anidada + 1) para dar algo como

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

Tal vez estoy pensando demasiado complicado aquí y hay una manera más fácil de hacer lo que quiera, pero creo que me encontré a mí mismo en una esquina mental que no puedo salir.

+0

Puede que exista un control '~' para hacer lo que desee, pero lo haría en 2 pasos: calcule el elemento más ancho, luego cree una cadena de formato (con formato) usando eso, luego llame formato para construir la tabla. Entonces es una función de 3 líneas en lugar de una función de 1 línea. :-) – Ken

Respuesta

3

Suponiendo que el ancho requerido está obligado a width, entonces usted puede hacer esto:

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

5 ha sido sustituido por V y width se ha añadido como un argumento a FORMAT/

editar: la respuesta original no cuenta correctamente para las directivas anidadas

En una cadena de control de formato V se puede usar en lugar de cualquier valor constante, lo que indica que el valor correspondiente debe tomarse de la lista de argumentos en su lugar.

Puede probar esto:

(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)) 

Esta cadena de formato requiere la anchura deseada a preceder a cada valor. La expresión (mapcar ...) logra esto.

+1

+1 Buena respuesta. El ancho máximo es al menos fácil de calcular (al menos si todos los números son positivos). Por ejemplo, '(1+ (aplicar # 'max (mapcar #') (lambda (x) (floor (log x 10))) '(1 10 100 1000 200000))))'. –

+0

He rechazado conscientemente esta solución porque el ajuste ad hoc del ancho en la lista de argumentos me parece innecesariamente complicado y derrochador. – Svante

+0

+1 y aceptado porque 'V' era exactamente lo que estaba buscando (y lo eché de menos en repetidas ocasiones). Veo el punto de Svanet, así que +1 también :) –

5

creo que usted tiene dos opciones: dejar que la magia format ir y utilizar otras construcciones de bucle o generar la cadena de formato en sí:

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

La definición de longest-member se deja como ejercicio para el lector.

Cuestiones relacionadas