You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 10:12:35