所以我有解析器,并且想使用第一个确实返回非空值的解析器。我将如何做得最优雅?
return parsers.map { it.parse(content) }.firstOrNull { it != null }
在选择第一个解析器之前会映射所有(百万个)解析器。
return parsers.firstOrNull { it.parse(content) != null }?.parse(content)
会再次运行(昂贵?)parse()
。
我知道我可以
for (parser in parsers) {
val result = parser.parse(content)
if (result != null) {
return result
}
}
return null
parsers.forEach { it.parse(content)?.run { return this } }
return null
是我能得到的最短的东西,但阅读起来并不好。
我很确定这里有一个我看不到的快捷方式。
答案 0 :(得分:6)
使用序列。它使您的计算变得懒惰,因此您只需要计算parse
的次数即可。
return parsers.asSequence()
.map { it.parse(content) }
.find { it != null }
答案 1 :(得分:4)
作为Sequence
开销的替代方法,或不必要地映射许多值,您可以使用扩展方法,例如:
inline fun <T, R> List<T>.firstMappedNotNull(transform: (T) -> R): R? {
for (e in this)
return transform(e) ?: continue
return null
}
这使用最少的映射函数调用和临时对象。它必须以命令式的方式编写,但是它很短,并且使您自己的代码简短,清晰且功能强大。
(如果列表为空或每个映射返回null
,则此版本将返回null
。您当然可以更改签名和最后一行以引发异常。)
可惜的是,该函数尚未在标准库中提供。但是添加您自己的很容易!
答案 2 :(得分:3)
此外,您可以使用以下代码:
parsers.asSequence()
.mapNotNull { it.parse(content) }
.firstOrNull()