2015-01-30 21 views
8

Dato:.Come catena di molteplici metodi di RxJava groupBy() come groupBy() groupBy() ingresso

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

Gruppo i numeri di pari o dispari e poi con minore o maggiore di 5.

uscita prevista:

[[1, 3, 5], [2, 4], [6, 8, 10], [7, 9]] 

l'ordine di uscita non è limitata.

Ora sto utilizzando il seguente approccio:

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)); 
    }); 

noti che ObservableUtils è scritto da me per semplificare il codice.

Ma non sono soddisfatto perché non è ancora abbastanza breve da indicare semplicemente l'obiettivo.

Quello che mi aspettavo è come il seguente:

Observable.range(1, 10) 
    .groupBy(n -> n % 2 == 0) 
    .groupBy(n -> n > 5) 
    .subscribe(...); 

Per ora posso ridursi solo a:

Observable.range(1, 10) 
    .lift(new OperatorGroupByGroup(n -> n % 2 == 0)) 
    .lift(new OperatorGroupByGroup(n -> n > 5)) 
    .subscribe(...); 

devo ancora scrivere la classe OperatorGroupByGroup che è un po 'complesso. Qualche suggerimento per migliorare?

risposta

2

Ho scritto un campione per OperatorGroupByGroup che, sulla base OperatorGroupBy:

https://github.com/yongjhih/RxJava-GroupByTest

Usage:

git clone https://github.com/yongjhih/RxJava-GroupByTest.git 
./gradlew execute 

Ma ho modificato il codice di prova a causa della mia implementazione OperatorGroupByGroup:

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)); 
    }); 

Penso che qualcuno lo farebbe meglio.

2

Provare a farlo in questo modo.

Observables.range(1,10) 
    .groupBy(n -> n % 2 == 0) 
    .flatMap(grp -> grp.groupBy(n -> n > 5).flatMap(grp2 -> grp2.toList())) 
    .subscribe(...) 
1

Ho due suggerimenti che penso siano entrambi abbastanza concisi ed eleganti.

Primo:

Observable.range(1, 10) 
    .groupBy(n -> n % 2 == 0) 
    .flatMap(g -> g.groupBy(n -> n > 5)) 
    .subscribe(...); 

che è quasi buono come la vostra aspettativa, solo un ulteriore .flatMap(). L'unico problema? Perdi la prima chiave, ma non sono sicuro che la stai usando comunque.

Secondo fabbisogno dichiarare una semplice classe Key che può contenere i risultati di entrambe le condizioni e disporre dell'implementazione corretta equals(). In altre parole uno Pair. Poi si può fare:

Observable.range(1, 10) 
    .groupBy(n -> new Key(n % 2 == 0, n > 5)) 
    .subscribe(...); 

Questo ha lo svantaggio di essere meno componibile, quando si dispone di entrambe le condizioni nello stesso .groupBy() chiamata invece di incatenato.Il vantaggio è che puoi usare una chiave combinata che trattiene i risultati di entrambe le tue condizioni se ne hai bisogno.