Kotlin是否有类似Scala的span方法?可合并takeWhile与dropWhile
Kotlin中是否有类似Scala的span方法?
Kotlin标准库没有内置和Scala span 功能完全一致的方法——也就是一次性返回满足条件的前缀和剩余后缀、避免重复遍历的方法。
替代方案
你自行实现的String扩展函数是可行的,针对更通用的集合类型(如List、Iterable),还可以实现一次遍历完成分割的版本,进一步优化性能:
针对List的高效实现
fun <T> List<T>.span(predicate: (T) -> Boolean): Pair<List<T>, List<T>> { val splitIndex = indexOfFirst { !predicate(it) }.takeIf { it != -1 } ?: size return subList(0, splitIndex) to subList(splitIndex, size) }
这个实现通过indexOfFirst找到第一个不满足条件的元素位置,再利用subList(视图操作,不复制元素)分割列表,全程只遍历一次。
通用Iterable实现
如果需要支持所有Iterable类型,可以通过迭代器一次遍历完成前缀和后缀的收集:
fun <T> Iterable<T>.span(predicate: (T) -> Boolean): Pair<List<T>, List<T>> { val iterator = iterator() val prefix = mutableListOf<T>() // 收集满足条件的前缀 while (iterator.hasNext()) { val item = iterator.next() if (predicate(item)) { prefix.add(item) } else { // 收集剩余后缀(包括当前不满足条件的元素) val suffix = mutableListOf<T>().apply { add(item) addAll(iterator) } return prefix to suffix } } // 所有元素都满足条件的情况 return prefix to emptyList() }
你的String实现说明
你编写的String扩展函数:
fun String.span(predicate: (Char) -> Boolean) = this.takeWhile(predicate).let { prefix -> Pair(prefix, this.drop(prefix.length)) }
对于String场景已经足够高效:takeWhile遍历到第一个不满足条件的字符后停止,而drop(prefix.length)是基于字符串索引的直接截取,不会再次遍历整个字符串。
内容的提问来源于stack exchange,提问作者tpdi
相关产品推荐
相关产品推荐

