2016-07-01 6 views
4

Ich bin ziemlich neu bei RxJava.Erstes Element eines GroupedObservable mit RxJava nehmen

Ich versuche Elemente mit einem bestimmten Schlüssel zu gruppieren und den ersten Wert jedes Schlüssels zu nehmen.

Zum Beispiel Gruppe diese Namen durch ihre Anfangsbuchstaben und drucken Sie die erste für jede Gruppe:

Observable<String> names = Observable.just(
          "John", "Steve", "Ruth", 
          "Sam", "Jane", "James"); 

Hier ist, was ich bisher versucht:

1. versuchen:

names.groupBy(s -> s.charAt(0)) 
    .flatMap(grp -> grp.first()) 
    .subscribe(s -> System.out.println(s)); 

FEHLGESCHLAGEN!: Alle Namen werden gedruckt.

2. versuchen:

names.groupBy(s -> s.charAt(0)) 
    .subscribe(grp -> grp 
         .first() 
         .subscribe(System.out::println)); 

erneut nicht gelungen!: alle Namen noch gedruckt werden ...

gelang es mir, das erwartete Ergebnis zu erhalten, indem jede GroupedObservable reduziert:

1. Versuch, mit reduzieren:

names.groupBy(s -> s.charAt(0)) 
    .flatMap(grp -> grp.reduce((a, b) -> a)) 
    .subscribe(s -> System.out.println(s)); 

zweiten Versuch, mit reduzieren:

names.groupBy(s -> s.charAt(0)) 
    .subscribe(grp -> grp 
         .reduce((a, b) -> a) 
         .subscribe(System.out::println)); 

Aber diese Lösung ist nicht ich Deal. In einer realen Situation würde dies eine teuere Berechnung erfordern und der reduce() Operator würde viel länger zum Berechnen (Berechnen aller Werte) brauchen als der first() Operator (Berechnen von nur einem Wert nach Schlüssel).

+1

Was ist mit 'names.distinct (s -> s.charAt (0)). Subscribe (/ ** /);'? – rciovati

+0

@RiccardoCiovati interresting Weg, um das Problem zu lösen. Es funktioniert gut für das eigentliche Beispiel. Leider trifft es nicht auf meinen eigentlichen Code zu, der komplexer ist. ;) –

Antwort

3

Dies ist aufgrund der Eigenschaft groupBy: Wenn eine Gruppe abgebrochen (nicht mehr beobachtet), kann eine neue Gruppe mit dem gleichen Schlüssel gestartet werden. Hier wird first nach dem ersten Element abgemeldet und das nachfolgende Element mit demselben Schlüssel erstellt die Gruppe neu.

Sie können dies über einige publish Betrug verhindern:

Observable<String> names = Observable.just(
     "John", "Steve", "Ruth", 
     "Sam", "Jane", "James"); 

names.groupBy(s -> s.charAt(0)) 
.flatMap(grp -> grp.publish(o -> o.first().concatWith(o.ignoreElements()))) 
.subscribe(s -> System.out.println(s)); 

Hier habe ich die Gruppe teilen und eine spezielle Ausgabe zu erzeugen; eine Verkettung des ersten Elements mit dem Ende der gesamten Gruppe (Elemente ignorieren).

+0

Danke für die Erklärung. Ich finde das ein wenig kontraintuitiv. Ich muss wahrscheinlich die Dokumente darüber lesen. –