如何找到不为null的第一个元素的方法结果?

时间:2019-06-18 05:31:50

标签: kotlin

所以我有解析器,并且想使用第一个确实返回非空值的解析器。我将如何做得最优雅?

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

是我能得到的最短的东西,但阅读起来并不好。

我很确定这里有一个我看不到的快捷方式。

3 个答案:

答案 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()