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