假设我有一个Sequence<Int>
来源未知(不一定来自集合)且大小未知但有限的:
val seq = sequenceOf(1, 2, -3, 4, 5, /* ... */)
假设序列足够大,不希望将整个序列转换为List
.
我想获取序列的最后一个元素:
val last = seq.last()
但我也想捕获可能出现的任何“无效”元素(假设负数无效)并返回第一个此类元素:
val invalid = seq.first { it < 0 }
但我怎样才能同时做这两件事呢?
val lastUnlessInvalidElementPresent = seq.firstOrNull { it < 0 } ?: seq.last()
问题是这?: seq.last()
不起作用,因为当firstOrNull
返回 null 时,整个序列已被消耗。
我可以迭代地执行此操作,但更喜欢功能性解决方案。
我认为使用内置函数不容易做到这一点,因为Last是一个有点特殊的谓词。
调整现有的
lastOrNull
来测试谓词 (it < 0
) 的第一次出现将如下所示:现在您可以使用它
seq.firstOrLastOrNull { it < 0 }
来获得您想要的东西。从性能角度来看,这应该与内置函数没有什么不同。您可能需要考虑为该函数使用更具描述性的名称。
您可以使用
fold()
一个简单的数据类,该数据类保存您的值以及一个标志,指示您是否仍处于“获取最后”模式或已经处于“遇到无效值,让我们保留它”模式:但这种方法有两个缺点:
fold()
即使遇到无效元素,仍然会消耗完整的序列操场
最后我想出了我自己的简洁解决方案:
它几乎是函数式的,但它不是纯函数式的,因为它使用了可变变量。