是否有更短的替代 Kotlin 已弃用的 String.capitalize() 函数?
Is there a shorter replacement for Kotlin's deprecated String.capitalize() function?
Kotlin 弃用了 String
class 上的 capitalize
函数,并且他们建议的替换太长了。这是一个例子,说明他们在弃用它方面做出了正确的决定,但在用户体验方面却做出了错误的决定。
例如,这段代码:
val x = listOf("foo", "bar", "baz").map { it.capitalize() }
被IDE“清理”成为:
val x = listOf("foo", "bar", "baz").map { it.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(
Locale.getDefault()
) else it.toString()
} }
这太丑了。我们能做些什么?
一个简洁的解决方案是在 String 上定义一个新的扩展函数,它用一个更简洁的名字隐藏了血淋淋的细节:
/**
* Replacement for Kotlin's deprecated `capitalize()` function.
*/
fun String.capitalized(): String {
return this.replaceFirstChar {
if (it.isLowerCase())
it.titlecase(Locale.getDefault())
else it.toString()
}
}
现在您的旧代码可以如下所示:
val x = listOf("foo", "bar", "baz").map { it.capitalized() }
您需要在一些可以轻松导入的包的顶层定义扩展函数。例如,如果您有一个名为 my.package.KotlinUtils
(KotlinUtils.kt
) 的 kotlin 文件,并且您将定义放入其中,如下所示:
package my.package
fun String.capitalized(): String {...}
然后你可以将它导入到你的其他包中:
import my.package.capitalized
建议的替换很丑陋,因为它需要等同于 capitalize()
曾经做过的事情:
- 取决于默认语言环境
- 不将大写第一个字符转换为首字母大写(例如,大写不会将前导 'DŽ' 转换为 'Dž' - 此处均为单个字符,请尝试 select 它们)
如果您不太在意这种行为,您可以使用一个更简单的表达式,使用不变的语言环境并无条件地将第一个字符转换为大写字母:
val x = listOf("foo", "bar", "baz").map { it.replaceFirstChar(Char::titlecase) }
这意味着如果第一个字符像 'DŽ'
一样是大写的,它无论如何都会被转换成标题变体 'Dž'
,而原始代码不会触及它。这实际上可能是可取的。
capitalize()
被弃用的原因之一是该方法的行为不明确。例如:
- 行为 #2 很奇怪
- 句子中的单词不大写可能是意想不到的(C# 会在每个 space-separated 单词的标题中大写)
- 不小写单词的其他字符也可能出乎意料
如果您想有意保留当前的确切行为,但又希望使用起来更方便,您可以随时使用适合您的名称来滚动您自己的扩展函数(“capitalize(d)”可能不够给不知道的人的信息 reader):
fun String.titlecaseFirstCharIfItIsLowercase() = replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
}
或者对于具有将大写字符进行标题转换的不变语言环境的版本:
fun String.titlecaseFirstChar() = replaceFirstChar(Char::titlecase)
这个怎么样?
fun main() {
val x = listOf("foo", "bar", "baz").map { it[0].uppercase() + it.drop(1) }
println(x)
}
输出:
[Foo, Bar, Baz]
如果您不确定(可能您从 API 收到字符串)首字母是大写还是小写,您可以使用以下方法;
var title = "myTitle"
title.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else
it.toString()
}
新标题将是“MyTitle”
val fruits = listOf("baNana", "avocAdo", "apPle", "kiwifRuit")
fruits
.filter { it.startsWith("a") }
.sortedBy { it }
.map { it.lowercase().replaceFirstChar(Char::uppercase) }
.forEach { println(it) }
输出:
Apple
Avocado
您可以使用此扩展函数将 String 的第一个字符大写
fun String.capitalize(): String {
return this.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault())
else it.toString()
}
}
并像这样调用此方法
"abcd".capitalize()
您可以对原始字符串调用 replaceFirstChar 函数并将转换函数作为输入传递。转换函数获取第一个字符并使用 uppercase() 函数将其转换为大写字符。
val list = listOf("foo", "bar", "baz") .map {
it.replaceFirstChar { firstChar ->
firstChar.uppercase()
}
}
println("List - > $list")
输出
List - > [Foo, Bar, Baz]
Kotlin 弃用了 String
class 上的 capitalize
函数,并且他们建议的替换太长了。这是一个例子,说明他们在弃用它方面做出了正确的决定,但在用户体验方面却做出了错误的决定。
例如,这段代码:
val x = listOf("foo", "bar", "baz").map { it.capitalize() }
被IDE“清理”成为:
val x = listOf("foo", "bar", "baz").map { it.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(
Locale.getDefault()
) else it.toString()
} }
这太丑了。我们能做些什么?
一个简洁的解决方案是在 String 上定义一个新的扩展函数,它用一个更简洁的名字隐藏了血淋淋的细节:
/**
* Replacement for Kotlin's deprecated `capitalize()` function.
*/
fun String.capitalized(): String {
return this.replaceFirstChar {
if (it.isLowerCase())
it.titlecase(Locale.getDefault())
else it.toString()
}
}
现在您的旧代码可以如下所示:
val x = listOf("foo", "bar", "baz").map { it.capitalized() }
您需要在一些可以轻松导入的包的顶层定义扩展函数。例如,如果您有一个名为 my.package.KotlinUtils
(KotlinUtils.kt
) 的 kotlin 文件,并且您将定义放入其中,如下所示:
package my.package
fun String.capitalized(): String {...}
然后你可以将它导入到你的其他包中:
import my.package.capitalized
建议的替换很丑陋,因为它需要等同于 capitalize()
曾经做过的事情:
- 取决于默认语言环境
- 不将大写第一个字符转换为首字母大写(例如,大写不会将前导 'DŽ' 转换为 'Dž' - 此处均为单个字符,请尝试 select 它们)
如果您不太在意这种行为,您可以使用一个更简单的表达式,使用不变的语言环境并无条件地将第一个字符转换为大写字母:
val x = listOf("foo", "bar", "baz").map { it.replaceFirstChar(Char::titlecase) }
这意味着如果第一个字符像 'DŽ'
一样是大写的,它无论如何都会被转换成标题变体 'Dž'
,而原始代码不会触及它。这实际上可能是可取的。
capitalize()
被弃用的原因之一是该方法的行为不明确。例如:
- 行为 #2 很奇怪
- 句子中的单词不大写可能是意想不到的(C# 会在每个 space-separated 单词的标题中大写)
- 不小写单词的其他字符也可能出乎意料
如果您想有意保留当前的确切行为,但又希望使用起来更方便,您可以随时使用适合您的名称来滚动您自己的扩展函数(“capitalize(d)”可能不够给不知道的人的信息 reader):
fun String.titlecaseFirstCharIfItIsLowercase() = replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
}
或者对于具有将大写字符进行标题转换的不变语言环境的版本:
fun String.titlecaseFirstChar() = replaceFirstChar(Char::titlecase)
这个怎么样?
fun main() {
val x = listOf("foo", "bar", "baz").map { it[0].uppercase() + it.drop(1) }
println(x)
}
输出:
[Foo, Bar, Baz]
如果您不确定(可能您从 API 收到字符串)首字母是大写还是小写,您可以使用以下方法;
var title = "myTitle"
title.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else
it.toString()
}
新标题将是“MyTitle”
val fruits = listOf("baNana", "avocAdo", "apPle", "kiwifRuit")
fruits
.filter { it.startsWith("a") }
.sortedBy { it }
.map { it.lowercase().replaceFirstChar(Char::uppercase) }
.forEach { println(it) }
输出:
Apple
Avocado
您可以使用此扩展函数将 String 的第一个字符大写
fun String.capitalize(): String {
return this.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault())
else it.toString()
}
}
并像这样调用此方法
"abcd".capitalize()
您可以对原始字符串调用 replaceFirstChar 函数并将转换函数作为输入传递。转换函数获取第一个字符并使用 uppercase() 函数将其转换为大写字符。
val list = listOf("foo", "bar", "baz") .map {
it.replaceFirstChar { firstChar ->
firstChar.uppercase()
}
}
println("List - > $list")
输出
List - > [Foo, Bar, Baz]