提问人:Tim Baverstock 提问时间:5/26/2022 最后编辑:Tim Baverstock 更新时间:5/26/2022 访问量:150
在 Kotlin 中,如何在不计算两次的情况下测试和使用一个值?
In Kotlin, how can I test and use a value without computing it twice?
问:
每隔一段时间,我就会发现自己想要为某种过滤操作计算一个值,但当它已经消失在条件检查中时,我又想使用该值。
例如:
val found = list.firstOrNull { slowConversion(it).isWanted() }
if (found != null) {
something(found, slowConversion(found))
}
或
when {
other_conditions -> other_actions
list.any { it.contains(regex1) } -> something(list.firstOrNull { it.contains(regex1) } ?: "!!??")
}
对于 slowConversion(),我可以使用映射到成对的序列,尽管术语 first 和 second 有点混淆......
val pair = list.asSequence().map { it to slowConversion(it) }.firstOrNull { it.second.isWanted() }
if ( pair != null ) {
something(pair.first, pair.second)
}
或者如果我只想要转换,
val converted = list.firstNotNullOfOrNull { slowConversion(it).takeIf { it.isWanted() } }
但是,为了避免重复,我能想到的最好的办法是将动作部分移动到条件部分!when
fun case(s: List<String>, r: Regex) {
val match = s.firstOrNull { it.contains(r) }?.also { something(it) }
return match != null
}
when {
other_conditions -> other_actions
case(list, regex1) -> true
}
在这一点上,似乎我应该将一堆函数调用与 ||
other_things || case(list, regex1) || case(list, regex2) || catchAll(list)
对于其中任何一个,有更好或更简洁的东西吗?
答:
1赞
Arpit Shukla
5/26/2022
#1
你可以这样编写你的第一个示例:
for(element in list) {
val result = slowConversion(element)
if(result.isWanted()) {
something(element, result)
break
}
}
这可能看起来不是很像Kotlin,但我认为它非常简单易懂。
对于第二个示例,可以使用以下函数:find
when {
other_conditions -> other_actions
else -> list.find { it.contains(regex1) }?.let(::something)
}
如果你有多个正则表达式,只需遍历它们,
val regexes = listOf(regex1, regex2, ...)
for(regex in regexes) {
val element = list.find { it.contains(regex1) } ?: continue
something(element)
break
}
评论
0赞
Tim Baverstock
7/7/2022
谢谢。我想我对漂亮的语法太过炯炯有神。也许 Kotlin 还有创造更多神奇语法的余地,但“不,目前没有很神奇的方式”对我来说已经足够了。干杯。:)
评论
?.
?:
?.also{}
map
firstOrNull
firstNotNullofOrNull