2009-10-06 14 views
25

Non so perché Wikipedia lists Mathematica as a programming language with printf. Non sono riuscito a trovare l'equivalente in Mathematica.Equivalente Sprint in Mathematica?

Il mio compito specifico è quello di elaborare un elenco di file di dati con i numeri imbottite, che ho usato per farlo in bash con

fn=$(printf "filename_%05d" $n) 

La funzione più vicina che ho trovato in Mathematica è PaddedForm. E dopo alcuni tentativi ed errori, l'ho preso con

"filename_" <> PaddedForm[ [email protected]#, 4, NumberPadding -> {"0", ""} ]& 

E 'molto strano che devo usare il numero 4 per ottenere il risultato simile a quello che mi da "% 05d". Non capisco questo comportamento. Qualcuno può spiegarmelo?

Ed è il modo migliore per ottenere ciò che ero abituato a bash?

+0

Questo è strano: non sono mai stato a conoscenza di un equivalente di stampa in Mathematica. Ho usato PaddedForm (e tutti i tipi di controllo di precisione) molto prima. Ho anche guardato la documentazione di PaddedForm in abbondanza cercando di capire il carattere extra del padding. +1. Voglio sapere. – Cascabel

+1

La mia teoria è che Wikipedia elenca Mathematica come linguaggio con printf perché ha StringForm. Ma StringForm è un'ombra triste e pallida di printf. – Pillsy

+0

['IntegerString'] (http://reference.wolfram.com/language/ref/IntegerString.html) – yohai

risposta

9

Non userei lo PaddedForm per questo. In effetti, non sono sicuro che lo PaddedForm sia adatto a qualcosa. Invece, mi piacerebbe utilizzare il buon vecchio ToString, Characters e PadLeft, in questo modo:

toFixedWidth[n_Integer, width_Integer] := 
    StringJoin[PadLeft[Characters[ToString[n]], width, "0"]] 

quindi è possibile utilizzare StringForm e ToString per rendere il vostro nome del file:

toNumberedFileName[n_Integer] := 
    [email protected]["filename_``", toFixedWidth[n, 5]] 

Mathematica non è adatto a questo tipo di munging delle stringhe.

EDIT per aggiungere: Mathematica corretta non ha la funzionalità richiesta, ma la classe java.lang.String ha il metodo statico format() che prende printf argomenti -style. Puoi chiamarlo usando la funzionalità JLink di Mathematica abbastanza facilmente. Le prestazioni non sarà molto buono, ma per molti casi di utilizzo proprio non si cura più di tanto:

Needs["JLink`"]; 
LoadJavaClass["java.lang.String"]; 
LoadJavaClass["java.util.Locale"]; 
sprintf[fmt_, args___] := 
String`format[Locale`ENGLISH,fmt, 
    MakeJavaObject /@ 
    Replace[{args}, 
    {x_?NumericQ :> [email protected], 
    x : (_Real | _Integer | True | 
     False | _String | _?JavaObjectQ) :> x, 
    x_ :> MakeJavaExpr[x]}, 
    {1}]] 

Hai bisogno di fare un po 'di lavoro, perché JLink è un po' stupido sulle funzioni Java con un numero variabile di argomenti. Il metodo format() accetta una stringa di formato e un array di Java Object s, e Mathematica non eseguirà la conversione automaticamente, che è ciò per cui è disponibile lo MakeJavaObject.

+0

Questa è davvero una procedura molto complicata per una semplice funzione printf. – jxy

+0

Piccolo bug lì: "w" invece di "larghezza". – dreeves

+0

Grazie per la funzione java. Sembra il meglio che possiamo avere. – jxy

1

Sono d'accordo con Pillsy. Ecco come lo farei. Nota la pratica funzione cat, che ritengo una specie di sprintf (meno i segnaposti come fornisce StringForm) in quanto funziona come Stampa (puoi stampare qualsiasi concatenazione di espressioni senza convertire in String) ma genera una stringa invece di inviare allo stdout.

cat = [email protected]@(ToString/@{##})&; 

pad[x_, n_] := If[[email protected][x]>=n, cat[x], 
              [email protected]@PadLeft[[email protected][x],n,"0"]] 

cat["filename_", pad[#, 5]]& 

Questo è molto simile risposta di Pillsy ma penso cat lo rende un po 'più pulito. Inoltre, penso che sia più sicuro avere quel condizionale nella funzione pad, meglio avere il padding sbagliato del numero sbagliato.

5

Si potrebbe anche definire una funzione che passa tutti gli argomenti per StringForm [] e utilizzare IntegerString o le funzioni di imbottitura come accennato in precedenza:

Sprintf[args__] := StringForm[args__] // ToString; 
file = Sprintf["filename_``", IntegerString[n, 10, 5]]; 
8

ho incontrato lo stesso problema un po ', e ha deciso per codificare la mia funzione. Non l'ho fatto in Java, ma ho usato solo le operazioni con le stringhe in Mathematica. È risultato piuttosto lungo, dal momento che in realtà avevo anche bisogno della funzionalità% f, ma funziona, e ora ho un pacchetto che posso usare in qualsiasi momento. Ecco un link al progetto GitHub:

https://github.com/vlsd/MathPrintF

Viene fornito con istruzioni di installazione (in realtà solo copiare la directory da qualche parte nel $ PATH).

Spero che questo sia utile almeno ad alcuni.

2

IntegerString fa esattamente quello che ti serve. In questo caso sarebbe

IntegerString[x,10,5]