Sprintf相当于Mathematica?

时间:2009-10-06 16:18:23

标签: wolfram-mathematica

我不知道为什么维基百科lists Mathematica as a programming language with printf。我在Mathematica中找不到相应的东西。

我的具体任务是处理带有填充数字的数据文件列表,我曾经在bash中使用

进行处理
fn=$(printf "filename_%05d" $n)

我在Mathematica中找到的最接近的函数是PaddedForm。经过一些反复试验,我得到了

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

我必须使用数字4来获得与“%05d”相似的结果,这很奇怪。我根本不明白这种行为。有人可以向我解释一下吗?

这是实现我在bash中所习惯的最佳方式吗?

5 个答案:

答案 0 :(得分:9)

我不会使用PaddedForm。事实上,我不确定PaddedForm对任何事情都有好处。相反,我会使用好的ToStringCharactersPadLeft,如下所示:

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

然后,您可以使用StringFormToString来创建文件名:

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

Mathematica并不适合这种字符串。

要添加的编辑: Mathematica本身没有所需的功能,但java.lang.String类的静态方法format()采用printf - 样式参数。您可以非常轻松地使用Mathematica的JLink功能调用它。性能不会很好,但对于许多用例,你不会那么在意:

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

你需要做更多的工作,因为JLink对于具有可变数量参数的Java函数有点愚蠢。 format()方法采用格式字符串和Java Object数组,Mathematica不会自动执行转换,这就是MakeJavaObject的用途。

答案 1 :(得分:8)

我遇到了相同的问题,并决定编写自己的函数。我没有在Java中这样做,而只是在Mathematica中使用了字符串操作。结果很长,因为我实际上也需要%f功能,但它可以工作,现在我把它作为一个包,我可以随时使用。这是GitHub项目的链接:

https://github.com/vlsd/MathPrintF

它带有安装说明(实际上只是将目录复制到$ Path中的某个位置)。

希望这对至少一些人有帮助。

答案 2 :(得分:5)

您还可以定义一个函数,它将所有参数传递给StringForm []并使用IntegerString或填充函数,如前所述:

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

答案 3 :(得分:2)

IntegerString完全符合您的需要。在这种情况下,它将是

IntegerString[x,10,5]

答案 4 :(得分:1)

我同意Pillsy的看法。 这是我将如何做到这一点。 请注意方便的cat函数,我认为它类似于sprintf(减去像StringForm提供的占位符),因为它的工作方式类似于Print(您可以打印任何串联的表达式而不转换为String)但生成一个字符串而不是发送到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]]&

这与Pillsy的答案非常相似,但我认为cat使它更清洁。 另外,我认为在pad函数中使用条件更安全 - 更好的是填充错误而不是数字错误。