在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