2009-10-06 33 views
25

Tôi không biết tại sao Wikipedia lists Mathematica as a programming language with printf. Tôi chỉ không thể tìm thấy tương đương trong Mathematica.Tương đương Sprintf trong Mathematica?

nhiệm vụ cụ thể của tôi là để xử lý một danh sách các tập tin dữ liệu với số lượng đệm, mà tôi sử dụng để làm điều đó trong bash với

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

Chức năng gần nhất tôi tìm thấy trong Mathematica là PaddedForm. Và sau một số lần thử và sai, tôi đã nhận được nó với

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

Rất lạ khi tôi phải sử dụng số 4 để nhận được kết quả tương tự như những gì tôi nhận được từ "% 05d". Tôi không hiểu hành vi này chút nào. Ai đó có thể giải thích cho tôi?

Và đó có phải là cách tốt nhất để đạt được những gì tôi đã từng sử dụng?

+0

Thật lạ lùng - Tôi chưa bao giờ biết về bản in tương đương trong Mathematica. Tôi đã sử dụng PaddedForm (và tất cả các loại điều khiển chính xác) nhiều thứ trước đây. Tôi cũng đã nhìn chằm chằm vào tài liệu của PaddedForm, cố gắng tìm hiểu thêm về nhân vật đệm đó. +1. Tôi muốn biết. – Cascabel

+1

Lý thuyết của tôi là Wikipedia liệt kê Mathematica như một ngôn ngữ với printf bởi vì nó có StringForm. Nhưng StringForm là một bóng mờ nhạt của printf. – Pillsy

+0

['IntegerString'] (http://reference.wolfram.com/language/ref/IntegerString.html) – yohai

Trả lời

9

Tôi sẽ không sử dụng PaddedForm cho việc này. Trong thực tế, tôi không chắc chắn rằng PaddedForm là tốt cho hầu hết mọi thứ. Thay vào đó, tôi muốn sử dụng tốt cũ ToString, CharactersPadLeft, như vậy:

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

Sau đó, bạn có thể sử dụng StringFormToString để làm cho tên tập tin của bạn:

toNumberedFileName[n_Integer] := 
    [email protected]["filename_``", toFixedWidth[n, 5]] 

Mathematica không phải là rất phù hợp với loại dây buộc này.

EDIT thêm: Mathematica thích hợp không có các chức năng cần thiết, nhưng lớp java.lang.String có phương pháp tĩnh format() mà mất printf đối số kiểu. Bạn có thể gọi nó bằng cách sử dụng chức năng JLink của Mathematica khá dễ dàng. Hiệu suất sẽ không tốt lắm, nhưng đối với nhiều trường hợp sử dụng, bạn sẽ không quan tâm đến điều đó nhiều:

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

Bạn cần làm thêm một chút, vì JLink hơi ngu ngốc về các hàm Java với một số lượng đối số thay đổi. Phương thức format() nhận một chuỗi định dạng và một mảng Java Object s và Mathematica sẽ không thực hiện chuyển đổi tự động, đó là những gì mà MakeJavaObject có sẵn cho.

+0

Đây thực sự là thủ tục rất phức tạp cho một hàm printf đơn giản. – jxy

+0

Lỗi nhỏ ở đó: "w" thay vì "chiều rộng". – dreeves

+0

Cảm ơn bạn đã sử dụng chức năng java. Nó trông giống như tốt nhất chúng ta có thể có. – jxy

1

Tôi đồng ý với Pillsy. Đây là cách tôi sẽ làm. Lưu ý chức năng cat tiện dụng, mà tôi nghĩ giống như sprintf (trừ phần giữ chỗ như StringForm cung cấp) ở chỗ nó hoạt động như In (bạn có thể in bất kỳ kết nối nào biểu thức mà không chuyển thành Chuỗi) nhưng tạo chuỗi thay vì gửi để stdout.

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

Điều này rất giống với câu trả lời của Pillsy nhưng tôi nghĩ rằng cat làm cho nó sạch hơn một chút. Ngoài ra, tôi nghĩ rằng nó an toàn hơn để có điều kiện trong chức năng pad - tốt hơn để có padding sai hơn số sai.

5

Bạn cũng có thể xác định một chức năng mà vượt qua tất cả các đối số cho StringForm [] và sử dụng IntegerString hoặc chức năng đệm như đã đề cập trước đó:

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

tôi đã chạy vào cùng một vấn đề khá một chút, và quyết định để mã chức năng của riêng tôi. Tôi đã không làm điều đó trong Java nhưng thay vào đó chỉ sử dụng các hoạt động chuỗi trong Mathematica. Nó bật ra khá dài, vì tôi thực sự cũng cần% f chức năng, nhưng nó hoạt động, và bây giờ tôi có nó như là một gói mà tôi có thể sử dụng bất cứ lúc nào. Dưới đây là một liên kết đến các dự án GitHub:

https://github.com/vlsd/MathPrintF

Nó đi kèm với hướng dẫn cài đặt (thực sự chỉ là sao chép các thư mục ở đâu đó trong $ Path).

Hy vọng điều này sẽ hữu ích cho ít nhất một số.

2

IntegerString thực hiện chính xác những gì bạn cần. Trong trường hợp này, nó sẽ là

IntegerString[x,10,5]