在Kotlin中首先查找并转换序列

在Kotlin中首先查找并转换序列,kotlin,functional-programming,Kotlin,Functional Programming,我经常碰到这个问题,但没有看到一个常见的实现:如何习惯性地(功能性地)查找元素,在匹配后停止搜索,并返回不同的类型(即,将匹配的任何类型映射到另一个类型) 我已经能够解决这个问题了 fun <F,T> Sequence<F>.mapFirst(block: (F) -> T?): T? = fold(AtomicReference<T>()) { ref, from -> if (ref.get() != null) ret

我经常碰到这个问题,但没有看到一个常见的实现:如何习惯性地(功能性地)查找元素,在匹配后停止搜索,并返回不同的类型(即,将匹配的任何类型映射到另一个类型)

我已经能够解决这个问题了

fun <F,T> Sequence<F>.mapFirst(block: (F) -> T?): T? =
    fold(AtomicReference<T>()) { ref, from ->
        if (ref.get() != null) return@fold ref
        ref.set(block(from))
        ref
    }.get()

fun main() {
    Files.list(someDir).asSequence().map { it.toFile() }.mapFirst { file ->
        file.useLines { lines ->
            lines.mapFirst { line ->
                if (line == "123") line.toInt() else null
            }
        }
    }?.let { num ->
        println("num is $num") // will print 123 as an Int
    } ?: println("not a single file had a line eq to '123'")
}
fun Sequence.mapFirst(块:(F)->T?:T=
折叠(原子引用()){ref,from->
if(ref.get()!=null)return@fold裁判
参考集(块(从))
裁判
}.get()
主要内容(){
Files.list(someDir.asSequence().map{it.toFile()}.mapFirst{file->
file.useLines{lines->
lines.mapFirst{line->
if(line==“123”)line.toInt()否则为空
}
}
}?.让{num->
println(“num是$num”)//将123打印为Int
}?:println(“没有一个文件的行eq与'123'”)
}

但这并不会在匹配时停止(当
block()
返回非null时),而是消耗所有文件及其所有行。

一个简单的
for
循环就足以实现
mapFirst

fun <F,T> Sequence<F>.mapFirst(block: (F) -> T?): T? {
    for (e in this) { 
        block(e)?.let { return it }
    }
    return null
}

我不会映射您放弃的值,而是这样做:

sequenceOf(1, 2, 3)
    .firstOrNull() { it == 2 }
    ?.let { it * 2 } ?: 6

首先找到与条件匹配的值,然后根据需要对其进行变换。如果找不到匹配的元素,则指定一个默认值(在本例中为6)

更新了问题,以明确我正在寻找一种功能性方法。@YuriGeinish,你能澄清你所说的“功能性方法”是什么意思吗?Ilya的第二个例子在我看来很实用,就像
.asSequence().first{/*condition*/}?.let{/*transform*/}
:都没有使用任何可修改的状态或副作用。
sequenceOf(1, 2, 3)
    .firstOrNull() { it == 2 }
    ?.let { it * 2 } ?: 6