2017-04-10 7 views
1

RxJava2で単純なスライディングウィンドウ関数を実装しようとしていますが、私がしたいことをするのに苦労しています。RxJava2でスライディングウィンドウを実装する

私の目標は、オブジェクトのストリームを取るすなわち

["a", "b", "c", "d", "e"] 

各要素に隣接する要素を戻しますスライディングウィンドウを適用することです。その結果

すなわち:

["a", "b"] 
["a", "b", "c"] 
["b", "c", "d"] 
["c", "d", "e"] 
["d", "e"]. 

すなわち、

a----------------b----------------c----------------d----------------e 
↓    ↓    ↓    ↓    ↓ 
↓    ↓    ↓    ↓    ↓ 
↓    ↓    ↓    ↓    ↓ 
↓    ↓    ↓    ↓    ↓ 
["a", "b"]  ["a", "b", "c"] ["b", "c", "d"] ["c", "d", "e"] ["d", "e"] 

これを実現する方法を理解できないようです。 Googleグループの投稿は正しかったようですが、必要な結果を得られません。 https://groups.google.com/forum/#!topic/rxjava/k-U5BijXinU

+0

私は問題のタイトルが問題文には適していないと思います。スライディングウィンドウは、[this](http://stackoverflow.com/questions/8269916/what-is-sliding-window-algorithm-examples)のようなものですが、各要素の隣接要素が必要なようです。 – jrook

+0

ダイアグラムに問題があります。実際に入力として到着する前に、アイテムを出力として放出することはできません。例えば。アイテム "a"と "b"を受け取った後、次の隣接が "c"とは言えません。それ以外の場合は、 'buffer()'メソッドが行います。 –

+0

@jrook異なる境界条件を持つスライディングウィンドウと同じだと思います。 –

答えて

1

observableにList<Item>またはObservable<Item>を出すかどうかに応じて、buffer()またはwindow()の演算子を使用できます。解決策は、クリーンではないが、それは非常に簡単です:

Observable.fromArray("a", "b", "c", "d", "e") 
     .startWith("") 
     .buffer(3, 1) 
     .map(strings -> { 
      strings.remove(""); 
      return strings; 
     }) 
     .filter(strings -> strings.size() > 1) 

戻り@jrookとしておそらく

["a", "b"] 
["a", "b", "c"] 
["b", "c", "d"] 
["c", "d", "e"] 
["d", "e"] 
+0

これは完璧でしたが、より豊かなオブジェクト、つまりカスタムタイプを使用するときは、汎用のセンチネル要素(この場合は "")を作成する方法を理解できませんでした。私の場合、文字列は実際には例えばCustomerEvents。 –

+1

CustomerEventsクラスの一部の値を持つCustomerEventsのインスタンスを作成し、静的にします。次に、静的メンバーにアクセスすることによって、 "sentinal"オブジェクトに対してテストすることができます。 –

0

が、これは標準のウィンドウに最適ではない、と述べました。配列の大きさ自体は、あなたが要素のどちら側にいるかを知るのに十分な情報ではないので、単純な値クラスでラップします。

ここに私が行った解決策があります。それは明らかに大きなストリームの場合は良い解決策ではありません。なぜなら、観測可能なもの全体を読み込むことをブロックするからです。特定のユースケースでは間違いないかもしれません(私の場合はOKです)。

public static <R> ObservableTransformer<R, AdjacentPairing<R>> pairWithAdjacents() { 
    return upstream -> upstream 
     .toList() 
     .flatMapObservable(list -> { 
      ArrayList<AdjacentPairing<R>> pairings = new ArrayList<>(list.size()); 
      for (int i = 0; i < list.size(); i++) { 
      pairings.add(AdjacentPairing.from(
       i == 0 ? null : list.get(i - 1), 
       list.get(i), 
       i == list.size() -1 ? null : list.get(i + 1))); 
      } 
      return Observable.fromIterable(pairings); 
     }); 
    } 

    @AutoValue 
    public static abstract class AdjacentPairing<T> { 
    @Nullable 
    public abstract T getPrevious(); 
    public abstract T getElement(); 
    @Nullable 
    public abstract T getNext(); 

    public static <T> AdjacentPairing<T> from(@Nullable T previous, T element, @Nullable T next){ 
     return new AutoValue_RxUtils_AdjacentPairing<>(previous, element, next); 
    } 
    } 
+2

反応性プログラミングのように見えますが、あなたの人生は難しくなります。なぜこのようなタスクのためにRxJavaが必要ですか? –

関連する問題