Unwave sequence,Kotlin函数式/流式习惯用法

Unwave sequence,Kotlin函数式/流式习惯用法,kotlin,sequences,purely-functional,Kotlin,Sequences,Purely Functional,我有一个交错数据序列(固定步幅),我想将它减少到每个“结构”的单个值(n*步幅值到n个值) 我可以使用循环写入可变列表,并选择步骤作为读者索引,但我正在寻找更具功能性和可读性的方法。有什么想法吗 例如: 输入序列由RGB三元组(步幅3)组成,输出为灰度 命令式的方式是: fun greyscale(stream:List<Byte>):List<Byte>{ val out = ArrayList(stream.size / 3) var i = 0; v

我有一个交错数据序列(固定步幅),我想将它减少到每个“结构”的单个值(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
}
fun灰度(流:列表):列表{
val out=ArrayList(stream.size/3)
变量i=0;变量o=0
而(i
我如何在不显式实现函数和可变容器的情况下制作这样的东西,而完全基于函数扩展,如
.map
等?

排除了其余元素:
const val N=3
趣味灰度(流:列表)=(0到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
趣味灰度(流:列表)=(0到(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() }
趣味灰度(rgb:List):列表 =rgb.foldIndexed( 内阵列(rgb.size/3), {idx,acc,i-> acc[idx/3]=acc[idx/3]+i;acc }).map{(it/3.toByte()}
输出 in:[1,2,3,4,5,6]

输出:[2,5]


使用
ArrayList
add
last
的变体,一种可能的方法是根据元素的索引进行分组(在本例中为
/3
),并将这些组映射到它们的总和

stream.withIndex()
      .groupBy { it.index / 3 }
      .toSortedMap()
      .values
      .map { (it.sumBy { it.value } / 3).toByte() }
同样严格的功能,但使用Rx,可以通过使用

Kotlin 1.2(Milestone 1昨天发布)在集合中引入了
chunked
方法。它将集合分成给定大小的块。您可以使用它来实现您的功能:

fun greyscale(stream: List<Byte>): List<Byte> = 
      stream.chunked(3)
            .map { (it.sum() / 3).toByte() }
fun灰度(流:列表):列表=
流。分块(3)
.map{(it.sum()/3).toByte()}

与@marstran的答案类似,在Kotlin 1.2中,您可以使用
chunked
函数,但为其提供转换lambda:

fun greyscale(stream: List<Byte>): List<Byte> = 
      stream.chunked(3) { it.average().toByte() }
fun灰度(流:列表):列表=
stream.chunked(3){it.average().toByte()}

这种变体的优点是它不会为每个三元组实例化一个新列表,而是创建一个列表并在整个操作过程中重用它。

map/reduce/flatMap
?恐怕我不太明白你想做什么。你的投入和期望的产出是什么?你的问题太广泛了。你能描述清楚吗?增加了一个例子。这个问题并不宽泛,它相当抽象,因为它涉及用于多个问题的惯用语/模式。Kotlin 1.2-M1(EAP)定义了新的函数,将有助于解决这一问题。即
windowed(size:Int,step:Int)
但也
chunked(size:Int)
pairwise()
用于类似场景。有关详细信息,请参阅。一点也不。:)而且不需要
toSortedMap
,因为映射是按迭代顺序排序的。
Observable.from(stream)
          .window(3)
          .concatMap { it.reduce(Int::plus).toObservable() }
          .map { (it / 3).toByte() }
fun greyscale(stream: List<Byte>): List<Byte> = 
      stream.chunked(3)
            .map { (it.sum() / 3).toByte() }
fun greyscale(stream: List<Byte>): List<Byte> = 
      stream.chunked(3) { it.average().toByte() }