2009-10-06 20 views
25

No sé por qué Wikipedia lists Mathematica as a programming language with printf. Simplemente no pude encontrar el equivalente en Mathematica.equivalente de Sprintf en Mathematica?

Mi tarea específica es procesar una lista de archivos de datos con números de acolchados, que solía hacerlo en bash con

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

La función más cercano que encontré en Mathematica es PaddedForm. Y después de algún ensayo y error, lo tengo con

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

Es muy raro que tengo que usar el número 4 para obtener el resultado similar a lo que recibo de "% 05d". No entiendo este comportamiento en absoluto. ¿Alguien puede explicar me lo?

¿Y es la mejor manera de lograr lo que solía en bash?

+0

Eso es extraño: nunca tuve conocimiento de un equivalente de impresión en Mathematica. He usado mucho material PaddedForm (y todo tipo de control de precisión). También me he fijado en la documentación de PaddedForm tratando de descubrir el carácter adicional del relleno. +1. Quiero saber. – Cascabel

+1

Mi teoría es que Wikipedia enumera Mathematica como un lenguaje con printf porque tiene StringForm. Pero StringForm es una triste y pálida sombra de printf. – Pillsy

+0

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

Respuesta

9

No utilizaría PaddedForm para esto. De hecho, no estoy seguro de que PaddedForm sea bueno para cualquier cosa. En su lugar, me gustaría usar el bueno de ToString, Characters y PadLeft, así:

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

continuación, puede utilizar StringForm y ToString para que su nombre de archivo:

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

Mathematica no está bien adaptado a este tipo de munging de cuerdas.

EDITAR para añadir: Mathematica adecuada no tiene la funcionalidad requerida, pero la clase java.lang.String tiene el método estático que toma format()printf argumentos al estilo. Puede llamarlo utilizando la funcionalidad JLink de Mathematica con bastante facilidad. El rendimiento no será muy buena, pero para muchos casos de uso que simplemente no le importa mucho:

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}]] 

Es necesario hacer un poco más trabajo, porque JLINK es un poco tonta sobre las funciones de Java con una número de argumentos variable El método format() toma una cadena de formato y una matriz de Java Object s, y Mathematica no hará la conversión automáticamente, que es lo que el MakeJavaObject está ahí para.

+0

Este es un procedimiento muy complicado para una función de impresión sencilla. – jxy

+0

Error pequeño allí: "w" en lugar de "ancho". – dreeves

+0

Gracias por la función java. Parece lo mejor que podemos tener. – jxy

1

Estoy de acuerdo con Pillsy. Así es como lo haría. Observe la práctica función cat, que considero como algo así como sprintf (menos los marcadores de posición como StringForm) en que funciona como Imprimir (puede imprimir cualquier concatenación de expresiones sin convertir a Cadena) pero genera una cadena en lugar de enviar a 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]]& 

Esto es muy parecido a la respuesta de Pillsy pero creo cat hace que sea un poco más limpio. Además, creo que es más seguro tener esa función condicional en la almohadilla, es mejor tener el relleno incorrecto que el número incorrecto.

5

También puede definir una función que pasa todos los argumentos a StringForm [] y utilice IntegerString o las funciones de relleno como se ha mencionado anteriormente:

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

me he encontrado con el mismo problema un poco, y decidió para codificar mi propia función. No lo hice en Java sino que usé operaciones de cuerda en Mathematica. Resultó bastante extenso, ya que en realidad también necesitaba la funcionalidad% f, pero funciona, y ahora lo tengo como un paquete que puedo usar en cualquier momento. Aquí hay un enlace al proyecto GitHub:

https://github.com/vlsd/MathPrintF

Viene con instrucciones de instalación (en realidad sólo copiar el directorio en algún lugar de la ruta de $).

Espero que esto sea útil al menos para algunos.

2

IntegerString hace exactamente lo que necesita. En este caso sería

IntegerString[x,10,5]