Sprintf equivalent in Mathematica?

冷暖自知 提交于 2019-12-31 17:52:52

问题


I don't know why Wikipedia lists Mathematica as a programming language with printf. I just couldn't find the equivalent in Mathematica.

My specific task is to process a list of data files with padded numbers, which I used to do it in bash with

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

The closest function I found in Mathematica is PaddedForm. And after some trial and error, I got it with

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

It is very odd that I have to use the number 4 to get the result similar to what I get from "%05d". I don't understand this behavior at all. Can someone explain it to me?

And is it the best way to achieve what I used to in bash?


回答1:


I wouldn't use PaddedForm for this. In fact, I'm not sure that PaddedForm is good for much of anything. Instead, I'd use good old ToString, Characters and PadLeft, like so:

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

Then you can use StringForm and ToString to make your file name:

toNumberedFileName[n_Integer] :=
  ToString@StringForm["filename_``", toFixedWidth[n, 5]]

Mathematica is not well-suited to this kind of string munging.

EDIT to add: Mathematica proper doesn't have the required functionality, but the java.lang.String class has the static method format() which takes printf-style arguments. You can call out to it using Mathematica's JLink functionality pretty easily. The performance won't be very good, but for many use cases you just won't care that much:

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

You need to do a little more work, because JLink is a bit dumb about Java functions with a variable number of arguments. The format() method takes a format string and an array of Java Objects, and Mathematica won't do the conversion automatically, which is what the MakeJavaObject is there for.




回答2:


I've run into the same problem quite a bit, and decided to code my own function. I didn't do it in Java but instead just used string operations in Mathematica. It turned out quite lengthy, since I actually also needed %f functionality, but it works, and now I have it as a package that I can use at any time. Here's a link to the GitHub project:

https://github.com/vlsd/MathPrintF

It comes with installation instructions (really just copying the directory somewhere in the $Path).

Hope this will be helpful to at least some.




回答3:


You could also define a function which passes all arguments to StringForm[] and use IntegerString or the padding functions as previously mentioned:

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



回答4:


IntegerString does exactly what you need. In this case it would be

IntegerString[x,10,5]



回答5:


I agree with Pillsy. Here's how I would do it. Note the handy cat function, which I think of as kind of like sprintf (minus the placeholders like StringForm provides) in that it works like Print (you can print any concatenation of expressions without converting to String) but generates a string instead of sending to stdout.

cat = StringJoin@@(ToString/@{##})&;

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

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

This is very much like Pillsy's answer but I think cat makes it a little cleaner. Also, I think it's safer to have that conditional in the pad function -- better to have the padding wrong than the number wrong.



来源:https://stackoverflow.com/questions/1526617/sprintf-equivalent-in-mathematica

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!