Làm cách nào để sử dụng java.String.format trong Scala?


322

Tôi đang cố gắng sử dụng một .formatphương thức của một chuỗi. Nhưng nếu tôi đặt% 1,% 2, v.v. trong chuỗi, java.util.Un UnknownFormatConversionException sẽ bị ném vào một đoạn mã nguồn Java khó hiểu:

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ừ đây tôi hiểu rằng %char bị cấm. Nếu vậy, tôi nên sử dụng gì cho giữ chỗ đối số?

Tôi sử dụng Scala 2.8.

Câu trả lời:


302

Mặc dù tất cả các phản hồi trước đó đều đúng, nhưng tất cả đều bằng Java. Đây là một ví dụ về Scala:

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

Tôi cũng có một bài đăng trên blog về việc tạo ra formatnhư %toán tử của Python có thể hữu ích.


2
Rất nhiều ví dụ trong tài liệu JDK: docs.oracle.com/javase/7/docs/api/java/util/ mẹo
angelcervera

1
Bạn có thể đơn giản hóa bằng cách áp dụng formattrực tiếp vào chuỗi ký tự:"Hello %s, isn't %s cool?".format("Ivan", "Scala")
sotrh

298

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

Đây là một ví dụ về cách thích hợp để sử dụng điều 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 sử dụng một %ký tự theo sau bởi một số ký tự khác để cho phương thức biết nó sẽ hiển thị chuỗi như thế nào. %scó 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ê mọi 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.formatchỉ sử dụng một java.util.Formatter, vì vậy để mô tả đầy đủ các tùy chọn, bạn có thể thấy javadocs Formatter .

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ẽ thời gian 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.


127

Thay vì nhìn vào mã nguồn, bạn nên đọc cú pháp javadoc String.format ()Formatter .

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

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

Đầu ra:

Hello, world on line 20

Để làm những gì bạn đã cố gắng (sử dụng chỉ mục đối 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 );

Đầu ra:

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

70

Bạn có thể sử dụng cái này;

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

Đầu ra:

abbc


1
Tôi chưa bao giờ thấy loại hình này, nó rất hữu ích khi lặp lại chuỗi, thật tuyệt!
Domi.Zhang

8
+1 này giống với những gì bạn sử dụng làm nhà phát triển C #. Ở đó, chúng tôi sử dụng {0}{1}thay vì %1$%2$.
tro999

@ tro999 Tôi đến từ c # đất. Tôi đã quá quen với những dấu ngoặc được đánh số Tôi sẽ quên đó không phải là cách làm tiêu chuẩn. Nhìn thấy các dấu hiệu phần trăm mang tất cả trở lại mặc dù!
JonnyRaa

13

Cũng lưu ý rằng Scala mở rộng Chuỗi bằng một số phương thức (thông qua chuyển đổi ngầm định thành WrappingString do Predef mang đến) để bạn cũng có thể thực hiện các thao tác sau:

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


10

Trong Scala 2.10

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

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

1
Tôi cho rằng đây chỉ là một cú pháp đặc biệt của nối chuỗ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 đó). Tuy nhiên, String.Format lấy mẫu làm tham số và do đó, ví dụ có thể truy xuất mẫu từ tệp thuộc tính và như vậy. - Điều đó có thể với cú pháp trên không?
chiccodoro

Đó là phép nội suy Chuỗi, trong scala có hai loại: s "" và f "", 's' là chuỗi đơn giản và 'f' tương tự như printf, bạn thậm chí có thể xác định phép nội suy của riêng mình (Tôi chưa thử). Có $namenghĩa là nó cần đượ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 phép nội suy, ví dụs"Hello ${name.toUpperCase}, it's $weather today!"
Londo

3

Đây là một danh sách những gì String.formatcó thể làm. Tương tự đối vớiprintf

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 );    // |0012345,68| |-012345,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 đến bộ nội suy chuỗi "s" của Scala, tôi nghĩ rằng bộ nội suy chuỗi "f" của Scala có liên quan nhiều hơn đến câu hỏi ban đầu. Ví dụ được sử dụng một vài lần trong các phản hồi 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à lưu ý rằng:

  • formattedđược định nghĩa bằng một chuỗi có tiền tố với chữ "f". Đây là bộ nội suy chuỗi "f" (định dạng).
  • Bộ nội suy chuỗi "f" sử dụng java.util.Formatter
  • java.lang.String.format sử dụng tương tự java.util.Formatter

Điều thú vị về phép nội suy chuỗi là nó cho phép bạn xem biến nào đang được thay thế trực tiếp vào chuỗi thay vì phải khớp nó với các đối số với String.formatphương thức.


0

Trong scala, đối với Nội suy chuỗi, chúng ta có $ giúp tiết kiệm thời gian và làm cho cuộc sống của chúng ta dễ dàng hơn nhiều:

Ví dụ: Bạn muốn xác định một hàm lấy tên và tuổi đầu vào và nói Xin chào với tên đó và cho biết tuổi của nó. Điều đó 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 hàm 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, 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.