【问题标题】:Sprintf equivalent in Mathematica?Mathematica 中的 Sprintf 等价物?
【发布时间】:2010-12-04 08:09:15
【问题描述】:

我不知道为什么维基百科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 中实现的最佳方式吗?

【问题讨论】:

  • 这很奇怪 - 我从来没有意识到 Mathematica 中的 printf 等价物。我以前用过很多 PaddedForm(和各种精度控制)的东西。我还盯着 PaddedForm 文档大量试图找出填充的额外字符。 +1。我想知道。
  • 我的理论是 Wikipedia 将 Mathematica 列为带有 printf 的语言,因为它具有 StringForm。但 StringForm 是 printf 的悲哀、苍白的阴影。
  • 既然这个老问题再次出现,为什么没有人去修复维基百科页面。

标签: wolfram-mathematica


【解决方案1】:

我不会为此使用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 数组 Objects,而 Mathematica 不会自动进行转换,这就是 MakeJavaObject 的用途。

【讨论】:

  • 对于一个简单的 printf 函数来说,这确实是一个非常复杂的过程。
  • 那里的小错误:“w”而不是“width”。
  • 感谢 java 功能。它看起来是我们能拥有的最好的了。
【解决方案2】:

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

IntegerString[x,10,5]

【讨论】:

    【解决方案3】:

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

    https://github.com/vlsd/MathPrintF

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        我同意皮尔西的观点。 这就是我将如何做到的。 请注意方便的cat 函数,我认为它有点像 sprintf(减去 StringForm 提供的占位符),因为它的工作方式类似于 Print(您可以打印任何连接的表达式而无需转换为字符串)但生成一个字符串而不是发送到标准输出。

        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 函数中使用条件更安全——填充错误比数字错误更好。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-09-08
          • 1970-01-01
          • 2023-04-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-11-03
          相关资源
          最近更新 更多