27

我不知道为什么 Wikipedia将 Mathematica 列为带有 printf 的编程语言。我只是在 Mathematica 中找不到等价物。

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

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

我在 Mathematica 中找到的最接近的函数是PaddedForm. 经过一些试验和错误,我得到了它

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

很奇怪,我必须使用数字 4 来获得类似于我从“%05d”得到的结果。我根本不理解这种行为。有人可以向我解释吗?

这是实现我过去在 bash 中的最佳方式吗?

4

5 回答 5

9

我不会用PaddedForm这个。事实上,我不确定这PaddedForm对任何事情都有好处。相反,我会使用 good old和ToString,就像这样:CharactersPadLeft

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

然后你可以使用StringFormandToString来创建你的文件名:

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

Mathematica 不太适合这种字符串处理。

编辑添加: Mathematica 本身没有所需的功能,但java.lang.String该类具有format()采用printf-style 参数的静态方法。您可以很容易地使用 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用途。

于 2009-10-06T16:51:21.533 回答
8

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

https://github.com/vlsd/MathPrintF

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

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

于 2011-08-25T12:07:29.727 回答
5

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

Sprintf[args__] := StringForm[args__] // ToString;
file = Sprintf["filename_``", IntegerString[n, 10, 5]];
于 2011-06-08T16:13:13.357 回答
2

IntegerString完全满足您的需求。在这种情况下,它将是

IntegerString[x,10,5]
于 2014-10-21T20:53:42.187 回答
1

我同意皮尔西。这就是我将如何做到的。请注意这个方便的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 函数中有条件更安全——填充错误比数字错误更好。

于 2010-04-18T14:28:38.917 回答