对连续项目使用RXJava groupby

时间:2018-09-26 11:11:37

标签: java rx-java2

我有一个可以观察到的解析大型csv文件(无法容纳在内存中)并发出类似:

[{id=1, childId=1}, {id=1, childId=2}, {id=1, childId=3}, {id=2, childId=5}, {id=2, childId=6}, {id=1, childId=23}, {id=1, childId=18}]

一行一行。

使用groupBy时,我的输出类似于

[{id=1, childs=1,2,**323, 18**}, {id=2, childs=5,6}]

groupBy似乎很正常。但是我需要的是接收连续项目的分组元素,因此我想接收另一个元素中id = 1的最后一个项目。我希望总共收到3个元素。

因此,我想连续接收一个可观察到的相同键,而当我拥有不同的键时,我想接收另一个可观察到的(分组依据)。

提前谢谢

1 个答案:

答案 0 :(得分:1)

一种可能的解决方案是编写自定义ObservableTransformer。 我认为,最简单的解决方案是根据下一条规则将项目分组:if cell.Id!= previousCell.Id将其放在另一个组中。

data class Cell(val id: Int, val childId: Int)

Observable.fromIterable(cells)
                .map(object: Function<Cell, Pair<Int, Cell>> {
                    var latest: Int? = null
                    var groupNumber: Int = 0

                    override fun apply(t: Cell): Pair<Int, Cell> {
                        if(t.id != latest) {
                            latest = t.id
                            groupNumber++
                        }
                        return Pair(groupNumber, t)
                    }

                })
                .groupBy { it.first }

此后,具有相同id的所有顺序单元将在一组中。现在您可以做任何您想做的事。要获得预期的输出,请使用以下方法:

Observable.fromIterable(cells)
            .map(object: Function<Cell, Pair<Int, Cell>> {
                var latest: Int? = null
                var groupNumber: Int = 0

                override fun apply(t: Cell): Pair<Int, Cell> {
                    if(t.id != latest) {
                        latest = t.id
                        groupNumber++
                    }
                    return Pair(groupNumber, t)
                }

            })
            .groupBy { it.first }
            .flatMapSingle { group ->
                return@flatMapSingle group.reduce(Pair(group.key!!, mutableListOf())) { acc: Pair<Int, MutableList<Int>>, el: Pair<Int, Cell> ->
                    acc.second.add(el.second.childId)
                    return@reduce acc
                }
            }.toList()
            .subscribe({
                Log.d("TAG", it.toString())
            }, { e -> e.printStackTrace() })

输出将为[(1,[1,2,3]),(2,[5,6]),(3,[23,18])]。

该解决方案并不干净,但是可以根据需要运行。