Mathematica 中的 Sprintf 等效项?

发布于 2024-08-07 07:54:19 字数 580 浏览 5 评论 0原文

我不知道为什么 Wikipedia 将 Mathematica 列为带有 printf 的编程语言。我只是在 Mathematica 中找不到对应的东西。

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

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

我在 Mathematica 中找到的最接近的函数是 PlatedForm 来完成此操作。经过一番尝试和错误后,我得到了

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

它很奇怪,我必须使用数字 4 才能得到类似于我从“%05d”得到的结果。我完全不理解这种行为。有人可以向我解释一下吗?

这是实现我在 bash 中实现的目标的最佳方法吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

勿忘初心 2024-08-14 07:54:19

我不会为此使用 PlatedForm 。事实上,我不确定 PlatedForm 对很多事情都有好处。相反,我会使用旧的 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< /code> 是为了。

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.

原谅我要高飞 2024-08-14 07:54:19

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

https://github.com/vlsd/MathPrintF

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

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

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.

九局 2024-08-14 07:54:19

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

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

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]];
向日葵 2024-08-14 07:54:19

IntegerString 正是您所需要的。在这种情况下,它将是

IntegerString[x,10,5]

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

IntegerString[x,10,5]
厌倦 2024-08-14 07:54:19

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文