2011-01-06 12 views
6

Questa domanda probabilmente finirà con un facepalm, ma ci ho provato per un po 'e sono ancora bloccato nonostante la lettura attraverso l'iperspec.- Aiuto con la stampa di un tavolo

Fondamentalmente quello che voglio fare è qualcosa di simile

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

ma invece di codificare il 5 dovrebbe essere calcolata dalla lista (lunghezza dell'elemento più lungo da qualsiasi lista annidata + 1) per dare qualcosa come

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

Forse sto pensando troppo complicato qua e là un modo più semplice per fare quello che voglio, ma penso che mi sono imbattuto in un angolo mentale che non riesco a uscire.

+0

Potrebbe esserci un controllo '~' per fare ciò che vuoi, ma lo farei in 2 passaggi: calcola l'elemento più largo, quindi costruisci una stringa formato (con formato!) Usando quello, quindi chiama formattare per costruire la tabella. Quindi è una funzione a 3 linee invece che a 1 riga. :-) – Ken

risposta

3

Supponendo che la larghezza richiesta è destinata a width, allora si può fare questo:

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

5 è stato sostituito da V e width è stato aggiunto come argomento per FORMAT/

modifica: la risposta originale non corrispondeva correttamente alle direttive nidificate

In una stringa di controllo del formato V può essere usato al posto di qualsiasi valore costante, indicando invece che il valore corrispondente deve essere preso dall'elenco degli argomenti.

Si può provare questo:

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

Questa stringa di formato richiede la larghezza desiderata far precedere ciascun valore. L'espressione (mapcar ...) completa ciò.

+1

+1 Bella risposta. La larghezza massima è almeno facile da calcolare (almeno se tutti i numeri sono positivi). Ad esempio, '(1+ (applica # 'max (mapcar #' (lambda (x) (floor (log x 10))) '(1 10 100 1000 200000))))'. –

+0

Ho deliberatamente rifiutato questa soluzione perché la splicing ad hoc della larghezza nella lista degli argomenti sembra inutilmente complicata e dispendiosa per me. – Svante

+0

+1 e accettato poiché 'V' era esattamente quello che stavo cercando (e ho perso ripetutamente sembra). Vedo però il punto di Svanet, quindi +1 anche qui :) –

5

Penso che si hanno due opzioni: lasciare che la magia format andare e utilizzare altri costrutti di loop o generare la stringa di formato stesso:

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

La definizione di longest-member viene lasciato come esercizio per il lettore.