Kotlin-字符串格式化

315

Kotlin有一个很棒的功能叫做字符串模板。

val i = 10 
val s = "i = $i" // evaluates to "i = 10"

但是在模板中是否可以使用任何格式?例如,我想在Kotlin的字符串模板中格式化Double类型,至少设置小数点后的位数:

val pi = 3.14159265358979323
val s = "pi = $pi??" // How to make it "pi = 3.14"?

3
有没有适用于多个平台的解决方案? - KenIchi
1
至少可以使用.format作为解决方法。不幸的是,在KMM中,String.format仍然不可用,至少直到2022年。它不在stdlib.textkotlinx中。字符串模板很酷,但是C风格格式化是基础,我认为复杂性可能基于变量列表的变化,但仍然令人失望。 - superarts.org
@superarts.org 是的!刚刚遇到了这个问题!在KMM中没有String.format!令人惊讶的是,迄今为止,Kotlin在KMM中的大部分功能都可以正常使用,而且主要是将其从Java转换为Kotlin的练习,但像String.format这样的功能却不可用,真是太糟糕了。 另外,Array.plus(element)也不可用,但Array.plus(Array)是可用的 - 这种不一致性可能是一个疏忽。 - Mike
10个回答

369

不幸的是,目前字符串模板中没有内置的格式化支持。作为解决方法,您可以使用类似以下的方式:

"pi = ${pi.format(2)}"

你需要自己定义的.format(n)函数。

fun Double.format(digits: Int) = "%.${digits}f".format(this)

这仅适用于Kotlin/JVM。

显然,Kotlin目前缺少一些功能,我们将进行修复。


8
现在有货吗? - Ragunath Jawahar
75
我是否错了,或者这个东西四年后仍然不可用? - RDM
11
将其作为2020年新年礼物添加! - mark mark
12
你好,来自2022年的问候!仍然不可用吗? - Alex
14
你好,来自2023年的问候......看起来还是不可用。 - Martin Marconcini
显示剩余16条评论

193
作为一种解决方法,可以使用 Kotlin stdlib函数以一种良好的方式并且完全兼容Java的字符串格式(它只是Java的String.format()的包装器)。
请参阅Kotlin的文档 您的代码应该是:
val pi = 3.14159265358979323
val s = "pi = %.2f".format(pi)

2
我猜他指的是这份文档:https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#format-java.util.Locale-java.lang.String-java.lang.Object... - stuckj
@Rob 请参考文档中的讨论 - Matt Mc
适用于Kotlin 1.3.21。 - F. P. Freely

46

Kotlin 的 String 类现在有一个 format 函数,它内部使用 Java 的 String.format 方法:


/**
 * Uses this string as a format string and returns a string obtained by substituting the specified arguments,
 * using the default locale.
 */
@kotlin.internal.InlineOnly
public inline fun String.Companion.format(format: String, vararg args: Any?): String = java.lang.String.format(format, *args)

使用方法

val pi = 3.14159265358979323
val formatted = String.format("%.2f", pi) ;
println(formatted)
>>3.14

2
在 Kotlin v1.2.21 中找不到 String.Companion.format。有什么替代方案吗? - Sai

43

很简单,使用:

val str: String = "%.2f".format(3.14159)

8

由于String.format只是一个扩展函数(请参见此处),它在内部调用了java.lang.String.format,如果您需要更多的灵活性,可以使用Java的DecimalFormat编写自己的扩展函数:

fun Double.format(fracDigits: Int): String {
    val df = DecimalFormat()
    df.setMaximumFractionDigits(fracDigits)
    return df.format(this)
}

println(3.14159.format(2)) // 3.14

4
一些例子:

例如:

infix fun Double.f(fmt: String) = "%$fmt".format(this)
infix fun Double.f(fmt: Float) = "%${if (fmt < 1) fmt + 1 else fmt}f".format(this)

val pi = 3.14159265358979323

println("""pi = ${pi f ".2f"}""")
println("pi = ${pi f .2f}")


3

Kotlin 1.7.2

String的format方法接受一个格式化字符串和任意数量的可为空的Any类型参数。

fun String.Companion.format(format: String, vararg args: Any?) : String

真正的代码可能看起来像这样:

fun main() {
    
    val pi: Double = 3.141592653589
    val gravity: Double = 9.80665
    var str = String.Companion.format("%.2f %n%.2f", pi, gravity)
    
    println(str)
}

%n代表换行符,%f代表十进制浮点数。

结果如下:

//    3.14 
//    9.81

1

作为一个多平台的简单解决方案,您可以使用以下方法:

import kotlin.math.abs
import kotlin.math.pow

fun Number.simpleFormat(numberDigitsAfterSeparator: Int = 0, decimalSeparator: Char = ','): String {
    if(numberDigitsAfterSeparator < 0)
        throw IllegalArgumentException("numberDigitsAfterSeparator should be >= 0 but is $numberDigitsAfterSeparator")

    val prefix = this.toInt()
    if(numberDigitsAfterSeparator == 0)return "$prefix"

    val sign = if(this.toDouble() >= 0.0) "" else "-"

    val afterSeparatorPart = abs(this.toDouble() - prefix)
    val suffixInt = (10.0.pow(numberDigitsAfterSeparator) * afterSeparatorPart).toInt()
    val suffix = if(afterSeparatorPart >= 1.0) "$suffixInt" else addNullsBefore(suffixInt, numberDigitsAfterSeparator)
    return "$sign${abs(prefix)}$decimalSeparator$suffix"
}

fun addNullsBefore(suffixInt: Int, numberDigitsAfterSeparator: Int): String {
    var s = "$suffixInt"
    val len = s.length
    repeat(numberDigitsAfterSeparator - len) { _ -> s = "0$s" }
    return s
}

测试:

fun main() {


    println((-0.00001).simpleFormat(5))
    println(3.1415927.simpleFormat(2))
    println(3.99.simpleFormat(2))
    println((-3.99).simpleFormat(2))

    println(3.1415927.simpleFormat())
    println(3.99.simpleFormat())
    println((-3.99).simpleFormat())

    println((-3.99).simpleFormat(-1))
}

带有输出:

-0,00001
3,14
3,99
-3,99
3
3
-3
Exception in thread "main" java.lang.IllegalArgumentException: numberDigitsAfterSeparator should be >= 0 but is -1..

0

这是一个针对Android TextView的Kotlin字符串格式化示例:

val format = String.format("<font color=#3177a3> test1: <b>%s</b><br> test2: <b>%s</b><br> test3: <b>%s</b></font>", "value1", "value2", "value3")
textView.text = format

-6

它具有字符串格式化功能 示例:

fun printSum(a: Int, b: Int): Unit {
    println("sum of $a and $b is ${a + b}")
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接