每隔一段时间,我发现自己想为某种过滤操作计算一个值,但是当它已经消失在条件检查中时,又想使用这个值。
例如:
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(),我可以使用映射到成对的序列,尽管术语第一和第二有点混淆……
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)
是否有更好或更简洁的东西?
你可以这样写你的第一个例子:
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
}