2010-09-12 3 views
309

Tôi đang cố gắng sử dụng phương thức .format của chuỗi. Nhưng nếu tôi đặt% 1,% 2, vv trong chuỗi, java.util.UnknownFormatConversionException được ném trỏ đến một Java khó hiểu mã nguồn mảnh:Làm thế nào để sử dụng java.String.format trong Scala?

private void checkText(String s) { 

    int idx; 

    // If there are any '%' in the given string, we got a bad format 
    // specifier. 
    if ((idx = s.indexOf('%')) != -1) { 
     char c = (idx > s.length() - 2 ? '%' : s.charAt(idx + 1)); 
     throw new UnknownFormatConversionException(String.valueOf(c)); 
    } 
} 

Từ đó tôi hiểu rằng % char bị cấm. Nếu có, thì tôi nên sử dụng cái gì cho các trình giữ chỗ đối số?

Tôi sử dụng Scala 2.8.

Trả lời

293

Trong khi tất cả các câu trả lời trước là chính xác, tất cả đều là trong Java. Dưới đây là ví dụ về Scala:

val placeholder = "Hello %s, isn't %s cool?" 
val formatted = placeholder.format("Ivan", "Scala") 

Tôi cũng có bài đăng trên blog về making format like Python's % operator có thể hữu ích.

+56

Đặt tên biến "chuỗi" đốt cháy thêm một số cylces não cpu để nhận ra nó không phải là loại, nhưng chỉ một tên biến. Chỉ muốn chỉ ra rằng những điều nhỏ nhặt như vậy có thể tạo ra sự khác biệt khi giải thích điều gì đó. –

+1

Điểm tốt, tôi sẽ sửa lỗi đó. – pr1001

+29

+1 cho thông điệp phù hợp với Ivan! –

297

Bạn không cần sử dụng số để chỉ định vị trí. Theo mặc định, vị trí của đối số chỉ đơn giản là thứ tự mà nó xuất hiện trong chuỗi.

Dưới đây là một ví dụ về cách thích hợp để sử dụng này:

String result = String.format("The format method is %s!", "great"); 
// result now equals "The format method is great!". 

Bạn sẽ luôn luôn sử dụng một % tiếp theo một số nhân vật khác để cho phương pháp này biết làm thế nào nó sẽ hiển thị chuỗi. %s có lẽ là phổ biến nhất, và nó chỉ có nghĩa là đối số nên được coi là một chuỗi.

Tôi sẽ không liệt kê tất cả các tùy chọn, nhưng tôi sẽ đưa ra một vài ví dụ chỉ để cung cấp cho bạn một ý tưởng:

// we can specify the # of decimals we want to show for a floating point: 
String result = String.format("10/3 = %.2f", 10.0/3.0); 
// result now equals "10/3 = 3.33" 

// we can add commas to long numbers: 
result = String.format("Today we processed %,d transactions.", 1000000); 
// result now equals "Today we processed 1,000,000 transactions." 

String.format chỉ sử dụng một java.util.Formatter, vì vậy đối với một mô tả đầy đủ các tùy chọn bạn có thể xem Formatter javadocs.

Và, như BalusC đề cập, bạn sẽ thấy trong tài liệu có thể thay đổi thứ tự đối số mặc định nếu bạn cần. Tuy nhiên, có lẽ lần duy nhất bạn cần/muốn làm điều này là nếu bạn đang sử dụng cùng một đối số nhiều lần.

126

Thay vì xem mã nguồn, bạn nên đọc javadoc String.format()Formatter syntax.

Bạn chỉ định định dạng của giá trị sau%. Ví dụ cho số nguyên thập phân đó là d, và cho String nó là s:

String aString = "world"; 
int aInt = 20; 
String.format("Hello, %s on line %d", aString, aInt); 

Output:

Hello, world on line 20 

Để làm được những gì bạn đã cố gắng (sử dụng một chỉ số tham số), bạn sử dụng: *n*$,

String.format("Line:%2$d. Value:%1$s. Result: Hello %1$s at line %2$d", aString, aInt); 

Output:

Line:20. Value:world. Result: Hello world at line 20 
13

Cũng lưu ý rằng Scala kéo dài chuỗi với một số phương pháp (thông qua chuyển đổi ngầm để một WrappedString đưa vào bởi Predef), do đó bạn cũng có thể làm như sau:

val formattedString = "Hello %s, isn't %s cool?".format("Ivan", "Scala") 
11

các tài liệu tham khảo chính thức là lớp Formatter.

8

Trong Scala 2,10

val name = "Ivan" 
val weather = "sunny" 

s"Hello $name, it's $weather today!" 
+1

Tôi lấy nó rằng đây chỉ là một cú pháp đặc biệt của chuỗi nối (có nghĩa là $ name và $ weather là các tham chiếu cứng đến các biến được định nghĩa trước đó). String.Format tuy nhiên lấy mẫu như một tham số và do đó làm cho nó có thể ví dụ để truy xuất các mẫu từ một tập tin thuộc tính và như vậy. - Có thể với cú pháp trên không? – chiccodoro

+0

Gọi là nội suy chuỗi, bên trong scala có hai kiểu: s "" và f "", 's' là chuỗi đơn giản và 'f' tương tự với 'printf', bạn thậm chí có thể xác định nội suy của riêng bạn (Tôi chưa thử). '$ name' có nghĩa là nó cần phải được thay thế bằng giá trị của biến' name', bạn cũng có thể thực hiện thao tác trong nội suy, ví dụ 's" Hello $ {name.toUpperCase}, hôm nay là $ weather ! "' – Londo

70

Bạn có thể sử dụng;

String.format("%1$s %2$s %2$s %3$s", "a", "b", "c"); 

Output:

a b b c

+1

Tôi chưa bao giờ thấy loại sử dụng này, nó rất hữu ích khi lặp lại chuỗi, tuyệt vời! –

+8

+1 đây giống như những gì bạn sử dụng với tư cách là nhà phát triển C#. Ở đó, chúng ta sử dụng '{0}' và '{1}' thay vì '% 1 $' và '% 2 $'. – ashes999

+0

@ ashes999 Tôi đến từ đất C#. Tôi được sử dụng để đánh số khung tôi muốn forgotton đó không phải là cách tiêu chuẩn để làm việc. Nhìn thấy các dấu hiệu phần trăm mang lại tất cả trở lại mặc dù! –

3

Đây là một danh sách những gì String.format có thể làm. Cũng vậy với printf

int i = 123; 
o.printf("|%d|%d|%n" ,  i, -i);  // |123|-123| 
o.printf("|%5d|%5d|%n" ,  i, -i);  // | 123| –123| 
o.printf("|%-5d|%-5d|%n" , i, -i);  // |123 |-123 | 
o.printf("|%+-5d|%+-5d|%n" , i, -i);  // |+123 |-123 | 
o.printf("|%05d|%05d|%n%n", i, -i);  // |00123|-0123| 

o.printf("|%X|%x|%n", 0xabc, 0xabc);  // |ABC|abc| 
o.printf("|%04x|%#x|%n%n", 0xabc, 0xabc); // |0abc|0xabc| 

double d = 12345.678; 
o.printf("|%f|%f|%n" ,   d, -d); // |12345,678000|  |-12345,678000| 
o.printf("|%+f|%+f|%n" ,  d, -d); // |+12345,678000| |-12345,678000| 
o.printf("|% f|% f|%n" ,  d, -d); // | 12345,678000| |-12345,678000| 
o.printf("|%.2f|%.2f|%n" ,  d, -d); // |12345,68| |-12345,68| 
o.printf("|%,.2f|%,.2f|%n" , d, -d); // |12.345,68| |-12.345,68| 
o.printf("|%.2f|%(.2f|%n",  d, -d); // |12345,68| |(12345,68)| 
o.printf("|%10.2f|%10.2f|%n" , d, -d); // | 12345,68| | –12345,68| 
o.printf("|%010.2f|%010.2f|%n",d, -d); // |0,68| |-,68| 

String s = "Monsterbacke"; 
o.printf("%n|%s|%n", s);     // |Monsterbacke| 
o.printf("|%S|%n", s);     // |MONSTERBACKE| 
o.printf("|%20s|%n", s);     // |  Monsterbacke| 
o.printf("|%-20s|%n", s);     // |Monsterbacke  | 
o.printf("|%7s|%n", s);     // |Monsterbacke| 
o.printf("|%.7s|%n", s);     // |Monster| 
o.printf("|%20.7s|%n", s);    // |    Monster| 

Date t = new Date(); 
o.printf("%tT%n", t);      // 11:01:39 
o.printf("%tD%n", t);      // 04/18/08 
o.printf("%1$te. %1$tb%n", t);   // 18. Apr 
1

Mặc dù @Londo đề cập "s" chuỗi xen vào Scala, tôi nghĩ rằng Scala của "f" string interpolator là phù hợp hơn với câu hỏi ban đầu. Ví dụ sử dụng một vài lần trong phản ứng khác cũng có thể được viết (kể từ Scala 2.10) theo cách này:

scala> val name = "Ivan" 
name: String = Ivan 
scala> val thing = "Scala" 
thing: String = Scala 
scala> val formatted = f"Hello $name%s, isn't $thing%s cool?" 
formatted: String = Hello Ivan, isn't Scala cool? 

Kết nối với câu hỏi ban đầu là phải nhận thức được rằng:

  • formatted được định nghĩa với một chuỗi được bắt đầu bằng chữ "f". Đây là nội suy chuỗi "f" (định dạng).
  • Các "f" chuỗi xen vào sử dụng java.util.Formatter
  • java.lang.String.format sử dụng cùng một java.util.Formatter

Những điều tốt đẹp về chuỗi suy là nó cho phép bạn xem những biến đang được thay thế trực tiếp vào chuỗi thay vì phải phù hợp với đối số với phương pháp String.format.

0

Trong scala, cho chuỗi Interpolation chúng tôi có $ rằng tiết kiệm trong ngày và làm cho cuộc sống của chúng tôi rất dễ dàng:

Ví dụ: Bạn muốn xác định một hàm lấy tên đầu vào và tuổi tác và nói Xin chào Với tên và nói tuổi của nó. Đó có thể được viết như thế này:

def funcStringInterpolationDemo(name:String,age:Int)=s"Hey ! my name is $name and my age is $age" 

Do đó, Khi bạn gọi chức năng này: như thế này:

funcStringInterpolationDemo("Shivansh",22) 

đầu ra của nó sẽ là:

Hey ! my name is Shivansh and my age is 22 

Bạn có thể viết mã để thay đổi nó trong cùng một dòng, giống như nếu bạn muốn thêm 10 năm tuổi!

sau đó chức năng có thể là:

def funcStringInterpolationDemo(name:String,age:Int)=s"Hey ! my name is $name and my age is ${age+10}" 

Và bây giờ đầu ra sẽ là:

Hey ! my name is Shivansh and my age is 32