Given input:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Group the numbers by odd or even and then by less than or greater than 5.
Expected output:
[[1, 3, 5], [2, 4], [6, 8, 10], [7, 9]]
The order of the output isn't restricted.
I'm now using the following approach:
Observable.range(1, 10)
.groupBy(n -> n % 2 == 0)
.flatMap((GroupedObservable<Boolean, Integer> g) -> {
return Observable.just(g).flatMap(ObservableUtils.<Boolean, Integer>flatGroup()).groupBy(n -> n > 5);
})
.subscribe((final GroupedObservable<Boolean, Integer> g) -> {
Observable.just(g).flatMap(ObservableUtils.<Boolean, Integer>flatGroup()).forEach(n -> println(g + ": " + n));
});
Note that ObservableUtils is written by me to simplify the code.
But I'm not satisfied with it because it still not short enough to simply indicate the goal only.
What I expected is like the following:
Observable.range(1, 10)
.groupBy(n -> n % 2 == 0)
.groupBy(n -> n > 5)
.subscribe(...);
For now I can only shrink it to:
Observable.range(1, 10)
.lift(new OperatorGroupByGroup(n -> n % 2 == 0))
.lift(new OperatorGroupByGroup(n -> n > 5))
.subscribe(...);
I still have to write the OperatorGroupByGroup class which is a little bit complex. Any suggestion for improving?
Try to do it in this way.
Observables.range(1,10)
.groupBy( n -> n % 2 == 0)
.flatMap( grp -> grp.groupBy( n -> n > 5).flatMap( grp2 -> grp2.toList()))
.subscribe(...)
I wrote a sample for OperatorGroupByGroup that based on OperatorGroupBy:
https://github.com/yongjhih/RxJava-GroupByTest
Usage:
git clone https://github.com/yongjhih/RxJava-GroupByTest.git
./gradlew execute
But I modified testing code due to my OperatorGroupByGroup implementation:
Observable.range(1, 10)
.lift(new OperatorGroupByGroup<Integer, Boolean, Integer>(n -> n % 2 == 0))
.lift(new OperatorGroupByGroup<GroupedObservable<Boolean, Integer>, Boolean, Integer>(n -> n > 5))
.subscribe((final GroupedObservable<Boolean, Integer> g) -> {
Observable.just(g).flatMap(ObservableUtils.<Boolean, Integer>flatGroup()).forEach(n -> println(g + ": " + n));
});
I think somebody would do better.
I have two suggestions that I think are both pretty concise and elegant.
First:
Observable.range(1, 10)
.groupBy(n -> n % 2 == 0)
.flatMap(g -> g.groupBy(n -> n > 5))
.subscribe(...);
Which is almost as good as your expectation, just one additional .flatMap(). The only problem? You lose the first key, but I'm not sure you're using those anyway.
Second needs declaring a simple Key class that can hold results of both your conditions and have proper equals() implementation. In other words a Pair. Then you can do:
Observable.range(1, 10)
.groupBy(n -> new Key(n % 2 == 0, n > 5))
.subscribe(...);
This has the disadvantage of being less composable, as you have both conditions in the same .groupBy() call instead of chained. The advantage is that you can use a combined key that holds results of both your conditions if you need them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With