Kotlin 条件格式字符串
Kotlin conditional formatting string
我有三个变量:
val months: Long
val days: Long
val hours: Long
我想 return 这样的事情 :
3个月2天5小时
现在这将简单地转换为:
val str = "$months months, $days days and $hours hours"
如果我的 个月 必须是 0 和 天 作为 1 and hours as 0 那么它会像'0个月1天0小时'
但我要找的是“1 天”。我怎样才能完成它?
我绝对可以使用某种有条件的 StringBuilder 来完成这项工作,但是还有更好的 优雅 吗?
你觉得这怎么样?
fun formatTime(months: Long, days: Long, hours: Long): String =
listOf(
months to "months",
days to "days",
hours to "hours"
)
.filter { (length,_) -> length > 0L }
// You can add an optional map predicate to make singular and plurals
.map { (amount, label) -> amount to if(abs(amount)==1L) label.replace("s", "") else label }
.joinToString(separator=", ") { (length, label) -> "$length $label" }
.addressLastItem()
fun String.addressLastItem() =
if(this.count { it == ','} >= 1)
// Dirty hack to get it working quickly
this.reversed().replaceFirst(" ,", " dna ").reversed()
else
this
您可以看到它正在运行 over here
另一种不替换、计数或反转列表的变体:
fun formatTime(months: Long, days: Long, hours: Long): String {
val list = listOfNotNull(
months.formatOrNull("month", "months"),
days.formatOrNull("day", "days"),
hours.formatOrNull("hour", "hours"),
)
return if (list.isEmpty()) "all values <= 0"
else
listOfNotNull(
list.take(list.lastIndex).joinToString().takeIf(String::isNotEmpty),
list.lastOrNull()
).joinToString(" and ")
}
fun Long.formatOrNull(singular: String, plural: String = "${singular}s") = when {
this == 1L -> "$this $singular"
this > 1L -> "$this $plural"
else -> null
}
如果所有值都 <= 0,它也有回退...您也可以只使用空字符串或您喜欢的任何内容。
如果您不喜欢创建中间列表来连接字符串,您也可以在 else 路径中使用如下内容:
list.iterator().run {
buildString {
while (hasNext()) {
val part = next()
if (length > 0)
if (hasNext())
append(", ")
else
append(" and ")
append(part)
}
}
}
我有三个变量:
val months: Long
val days: Long
val hours: Long
我想 return 这样的事情 :
3个月2天5小时
现在这将简单地转换为:
val str = "$months months, $days days and $hours hours"
如果我的 个月 必须是 0 和 天 作为 1 and hours as 0 那么它会像'0个月1天0小时'
但我要找的是“1 天”。我怎样才能完成它?
我绝对可以使用某种有条件的 StringBuilder 来完成这项工作,但是还有更好的 优雅 吗?
你觉得这怎么样?
fun formatTime(months: Long, days: Long, hours: Long): String =
listOf(
months to "months",
days to "days",
hours to "hours"
)
.filter { (length,_) -> length > 0L }
// You can add an optional map predicate to make singular and plurals
.map { (amount, label) -> amount to if(abs(amount)==1L) label.replace("s", "") else label }
.joinToString(separator=", ") { (length, label) -> "$length $label" }
.addressLastItem()
fun String.addressLastItem() =
if(this.count { it == ','} >= 1)
// Dirty hack to get it working quickly
this.reversed().replaceFirst(" ,", " dna ").reversed()
else
this
您可以看到它正在运行 over here
另一种不替换、计数或反转列表的变体:
fun formatTime(months: Long, days: Long, hours: Long): String {
val list = listOfNotNull(
months.formatOrNull("month", "months"),
days.formatOrNull("day", "days"),
hours.formatOrNull("hour", "hours"),
)
return if (list.isEmpty()) "all values <= 0"
else
listOfNotNull(
list.take(list.lastIndex).joinToString().takeIf(String::isNotEmpty),
list.lastOrNull()
).joinToString(" and ")
}
fun Long.formatOrNull(singular: String, plural: String = "${singular}s") = when {
this == 1L -> "$this $singular"
this > 1L -> "$this $plural"
else -> null
}
如果所有值都 <= 0,它也有回退...您也可以只使用空字符串或您喜欢的任何内容。
如果您不喜欢创建中间列表来连接字符串,您也可以在 else 路径中使用如下内容:
list.iterator().run {
buildString {
while (hasNext()) {
val part = next()
if (length > 0)
if (hasNext())
append(", ")
else
append(" and ")
append(part)
}
}
}