Эквивалент Sprintf в Mathematica?
Я не знаю, почему Wikipedia перечисляет Mathematica как язык программирования с printf. Я просто не мог найти эквивалент в Mathematica.
Моя специальная задача - обработать список файлов данных с заполненными номерами, которые я использовал для этого в bash с помощью
fn=$(printf "filename_%05d" $n)
Ближайшая функция, найденная в Mathematica, PaddedForm
. И после некоторых проб и ошибок, я получил его с
"filename_" <> PaddedForm[ [email protected]#, 4, NumberPadding -> {"0", ""} ]&
Очень странно, что я должен использовать число 4, чтобы получить результат, аналогичный тому, что я получаю от "% 05d". Я вообще не понимаю этого поведения. Может кто-нибудь объяснить это мне?
И лучший способ добиться того, что я использовал в bash?
Ответы
Ответ 1
Я бы не использовал PaddedForm
для этого. На самом деле, я не уверен, что PaddedForm
хорош для большей части всего. Вместо этого я бы использовал старые добрые ToString
, Characters
и PadLeft
, например:
toFixedWidth[n_Integer, width_Integer] :=
StringJoin[PadLeft[Characters[ToString[n]], width, "0"]]
Затем вы можете использовать StringForm
и ToString
, чтобы создать свое имя файла:
toNumberedFileName[n_Integer] :=
[email protected]["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 :> [email protected],
x : (_Real | _Integer | True |
False | _String | _?JavaObjectQ) :> x,
x_ :> MakeJavaExpr[x]},
{1}]]
Вам нужно немного поработать, потому что JLink немного тупо о функциях Java с переменным числом аргументов. Метод format()
принимает строку формата и массив Java Object
s, и Mathematica не будет делать преобразование автоматически, что и есть MakeJavaObject
.
Ответ 2
Я столкнулся с одной и той же проблемой совсем немного и решил записать свою собственную функцию. Я не делал этого в Java, а вместо этого использовал только строковые операции в Mathematica. Это оказалось довольно продолжительным, так как я действительно нуждался в функциональности% f, но он работает, и теперь у меня есть пакет, который я могу использовать в любое время. Здесь ссылка на проект GitHub:
https://github.com/vlsd/MathPrintF
Он поставляется с инструкциями по установке (на самом деле просто копирует каталог где-то в $Path).
Надеюсь, что это будет полезно, по крайней мере, для некоторых.
Ответ 3
Вы также можете определить функцию, которая передает все аргументы в StringForm [] и использовать IntegerString или функции заполнения, как было упомянуто ранее:
Sprintf[args__] := StringForm[args__] // ToString;
file = Sprintf["filename_``", IntegerString[n, 10, 5]];
Ответ 4
IntegerString
делает именно то, что вам нужно. В этом случае это будет
IntegerString[x,10,5]
Ответ 5
Я согласен с Пиллси.
Вот как я это сделаю.
Обратите внимание на удобную функцию cat
, которая, как я полагаю, похожа на sprintf (за исключением тех, которые используются в StringForm), поскольку она работает как Print (вы можете распечатать любую конкатенацию выражений без преобразования в String), но генерирует строку вместо отправка на стандартный вывод.
cat = [email protected]@(ToString/@{##})&;
pad[x_, n_] := If[[email protected][x]>=n, cat[x],
[email protected]@PadLeft[[email protected][x],n,"0"]]
cat["filename_", pad[#, 5]]&
Это очень похоже на ответ Pillsy, но я думаю, что cat
делает его немного чище.
Кроме того, я считаю, что безопаснее иметь это условное значение в функции пэда - лучше иметь неправильное заполнение, чем неправильное число.