วิธีการใช้ java.String.format ใน Scala?


322

ฉันกำลังพยายามใช้.formatวิธีการของสายอักขระ แต่ถ้าฉันวาง% 1,% 2 ฯลฯ ในสตริง java.util.UnknownFormatConversionException จะถูกส่งออกไปชี้ไปยังส่วนซอร์สโค้ด Java ที่สับสน:

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));
    }
}

จากนี้ฉันเข้าใจว่า%ถ่านเป็นสิ่งต้องห้าม ถ้าเป็นเช่นนั้นฉันควรใช้ตัวยึดตำแหน่งอาร์กิวเมนต์อย่างไร

ฉันใช้Scala 2.8

คำตอบ:


302

ในขณะที่การตอบสนองก่อนหน้าทั้งหมดถูกต้อง แต่ทั้งหมดอยู่ใน Java นี่คือตัวอย่างของ Scala:

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

ฉันยังมีโพสต์บล็อกเกี่ยวกับการทำformatเหมือน%ตัวดำเนินการของงูใหญ่ที่อาจมีประโยชน์


2
ตัวอย่างมากมายในเอกสารประกอบของ JDK: docs.oracle.com/javase/7/docs/api/java/util/ ......
angelcervera

1
คุณสามารถทำให้ง่ายขึ้นโดยใช้formatโดยตรงกับตัวอักษรสตริง:"Hello %s, isn't %s cool?".format("Ivan", "Scala")
sotrh

298

คุณไม่จำเป็นต้องใช้ตัวเลขเพื่อระบุตำแหน่ง ตามค่าเริ่มต้นตำแหน่งของอาร์กิวเมนต์เป็นเพียงลำดับที่ปรากฏในสตริง

นี่คือตัวอย่างของวิธีที่เหมาะสมในการใช้สิ่งนี้:

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

คุณจะใช้%อักขระอื่นตามมาเพื่อให้วิธีการรู้วิธีที่จะแสดงสตริง %sอาจเป็นเรื่องที่พบได้บ่อยที่สุดและมันก็หมายความว่าอาร์กิวเมนต์ควรได้รับการปฏิบัติเสมือนเป็นสตริง

ฉันจะไม่แสดงรายการตัวเลือกทุกตัว แต่ฉันจะยกตัวอย่างบางอย่างเพื่อให้แนวคิดแก่คุณ:

// 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เพียงแค่ใช้java.util.Formatterเพื่อให้คำอธิบายที่เต็มรูปแบบของตัวเลือกที่คุณสามารถดูjavadocs ฟอร์แมต

และตามที่ BalusC กล่าวถึงคุณจะเห็นในเอกสารที่สามารถเปลี่ยนอาร์กิวเมนต์เริ่มต้นได้หากคุณต้องการ อย่างไรก็ตามอาจเป็นครั้งเดียวที่คุณต้องการ / ต้องการทำเช่นนี้หากคุณใช้อาร์กิวเมนต์เดียวกันมากกว่าหนึ่งครั้ง


127

แทนที่จะมองรหัสที่มาคุณควรอ่าน Javadoc String.format ()และไวยากรณ์ฟอร์แมต

คุณระบุรูปแบบของค่าหลัง% เช่นเป็นจำนวนเต็มทศนิยมdและสำหรับ String เป็นs:

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

เอาท์พุท:

Hello, world on line 20

ในการทำสิ่งที่คุณพยายาม (ใช้ดัชนีข้อโต้แย้ง) คุณใช้: *n*$,

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

เอาท์พุท:

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

70

คุณสามารถใช้สิ่งนี้;

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

เอาท์พุท:

abbc


1
ฉันไม่เคยเห็นการใช้งานแบบนี้มาก่อนมันมีประโยชน์มากเมื่อทำซ้ำสตริงดีมาก!
Domi.Zhang

8
+1 นี่คือสิ่งที่คุณใช้ในฐานะนักพัฒนา C # มีเราใช้{0}และ{1}แทนและ%1$ %2$
ashes999

@ ashes999 ฉันมาจาก c # land เช่นกัน ฉันเคยชินกับการใส่หมายเลขที่ฉันลืมไปแล้วว่าไม่ใช่วิธีมาตรฐานในการทำสิ่งต่าง ๆ การเห็นสัญญาณร้อยละทำให้ทุกอย่างกลับมา!
JonnyRaa

13

นอกจากนี้โปรดทราบว่า Scala ขยาย String ด้วยวิธีการจำนวนมาก (ผ่านการแปลงโดยนัยไปยัง WrappedString ซึ่งนำโดย Predef) เพื่อให้คุณสามารถทำสิ่งต่อไปนี้:

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


10

ใน Scala 2.10

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

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

1
ฉันคิดว่านี่เป็นเพียงรูปแบบพิเศษของการต่อสตริง (หมายถึงว่า $ name และ $ weather นั้นยากที่จะอ้างอิงถึงตัวแปรที่กำหนดไว้ก่อนหน้านี้) String.Format ใช้เทมเพลตเป็นพารามิเตอร์และทำให้เป็นไปได้เช่นในการเรียกคืนเท็มเพลตจากไฟล์คุณสมบัติและเช่น - เป็นไปได้ด้วยไวยากรณ์ข้างต้นหรือไม่
chiccodoro

มันคือการเรียกการแก้ไขสตริงภายในสกาล่ามีสองประเภท: s "" และ f "", 's' เป็นสตริงที่เรียบง่ายและ 'f' จะคล้ายกับprintfคุณยังสามารถกำหนดการแก้ไขของคุณเอง (ฉันไม่ได้ ลอง). $nameหมายความว่ามันจะต้องมีการเปลี่ยนค่าของตัวแปรที่nameคุณยังสามารถดำเนินการในการแก้ไขเช่นs"Hello ${name.toUpperCase}, it's $weather today!"
Londo

3

นี่คือรายการของสิ่งที่String.formatสามารถทำได้ เช่นเดียวกับ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 );    // |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

แม้ว่า @Londo พูดถึงผู้แทรกสตริง "s" ของ Scala แต่ฉันคิดว่าinterpolator สตริง "f"ของ Scala นั้นเกี่ยวข้องกับคำถามเดิมมากกว่า ตัวอย่างที่ใช้ในการตอบกลับอื่น ๆ อาจเขียนได้ (ตั้งแต่ Scala 2.10) ด้วยวิธีนี้:

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?

การเชื่อมต่อกับคำถามเดิมจะต้องทราบว่า:

  • formattedถูกกำหนดด้วยสตริงที่นำหน้าด้วยตัวอักษร "f" นี่คือ interpolator สตริง "f" (การจัดรูปแบบ)
  • เครื่องมือแก้ไขสตริง "f" ใช้ java.util.Formatter
  • java.lang.String.format ใช้เหมือนกัน java.util.Formatter

สิ่งที่ดีเกี่ยวกับการแก้ไขสตริงคือมันช่วยให้คุณเห็นว่าตัวแปรใดที่จะถูกแทนที่โดยตรงในสตริงแทนที่จะต้องจับคู่กับอาร์กิวเมนต์ของString.formatเมธอด


0

ในสกาล่าสำหรับการแก้ไขสตริงเรามี$ที่ช่วยประหยัดเวลาและทำให้ชีวิตของเราง่ายขึ้นมาก:

ตัวอย่างเช่น:คุณต้องการกำหนดฟังก์ชั่นที่ใช้ชื่อและอายุอินพุตและพูดว่าสวัสดีด้วยชื่อและบอกอายุของมัน ที่สามารถเขียนได้เช่นนี้

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

ดังนั้นเมื่อคุณเรียกใช้ฟังก์ชันนี้: เช่นนี้

funcStringInterpolationDemo("Shivansh",22)

มันจะเป็นผลลัพธ์:

Hey ! my name is Shivansh and my age is 22

คุณสามารถเขียนรหัสเพื่อเปลี่ยนในบรรทัดเดียวกันเช่นถ้าคุณต้องการที่จะเพิ่มอายุ 10 ปี!

จากนั้นฟังก์ชั่นอาจเป็น:

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

และตอนนี้ผลลัพธ์จะเป็น:

Hey ! my name is Shivansh and my age is 32
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.