Unweave序列,Kotlin功能/流式习语
我有一个交错的数据序列(与固定步幅),我想减少它为每个“结构”(n *跨度价值n值)单个值。
我可以使用循环写入到可变列表中,并为读者索引选定步骤,但是我正在寻找更多的功能和可读的方法。 有什么想法吗?
例如:输入序列由RGB三元组(步幅3)组成,输出为灰度。
命令的方式是这样的:
fun greyscale(stream:List<Byte>):List<Byte>{ val out = ArrayList(stream.size / 3) var i = 0; var o = 0 while(i < stream.size) out[o++]=(stream[i++] + stream[i++] + stream[i++])/3 return out }
我怎么能没有明确地实现一个函数和可变容器,而是纯粹的功能扩展如.map
等?
一种可能的方法是按元素的索引(在本例中为/3
)进行分组,并将这些组映射到它们的总和。
stream.withIndex() .groupBy { it.index / 3 } .toSortedMap() .values .map { (it.sumBy { it.value } / 3).toByte() }
同样严格的功能,但使用Rx,将可能通过使用window(long)
Observable.from(stream) .window(3) .concatMap { it.reduce(Int::plus).toObservable() } .map { (it / 3).toByte() }
科特林1.2(里程碑1昨天发布)带来了分类方法集合。 它将收集块分成一定大小的块。 你可以用它来实现你的功能:
fun greyscale(stream: List<Byte>): List<Byte> = stream.chunked(3) .map { (it.sum() / 3).toByte() }
排除其余元素:
const val N = 3 fun greyscale(stream: List<Byte>) = (0 until stream.size / N) .map { it * N } .map { stream.subList(it, it + N).sum() / N } .map(Int::toByte)
产量
[1,2,3,4,5,6] => [2,5]
[1,2,3,4,5] => [2]
包括其余的元素:
const val N = 3 fun greyscale(stream: List<Byte>) = (0 until (stream.size + N - 1) / N) .map { it * N } .map { stream.subList(it, minOf(stream.size, it + N)).sum() / N } .map(Int::toByte)
产量
[1,2,3,4,5,6] => [2,5]
[1,2,3,4,5] => [2,3]
最好的是我的能力是这样的:
fun grayscale(rgb:List<Byte>):List<Byte> = rgb.foldIndexed( IntArray(rgb.size / 3), { idx, acc, i -> acc[idx / 3] = acc[idx / 3] + i; acc }).map{ (it / 3).toByte() }
产量
在:[1,2,3,4,5,6]
出:[2,5]
和ArrayList
add
和last
变种