2017-04-10 129 views
1

我想在RxJava2中實現一個簡單的滑動窗口功能,但努力做我想做的事情。在RxJava2中實現滑動窗口

我的目標是採取對象的流,即

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

並應用滑動窗口將返回相鄰元素中的元素。

即導致:

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

I.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

取決於您希望您的觀測值發出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) 

回報

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

這將是完美的,但我不知道如何使用更豐富的對象,即自定義類型時,如何製作通用的哨兵元素(在本例中爲「」)。在我的情況下,字符串實際上是CustomerEvents。 –

+1

使用CustomerEvents類中的某些值創建CustomerEvents實例並將其設爲靜態。然後,您可以通過訪問靜態成員來測試「最終目標」客體。 –

0

也許正如@jrook說,這不是一個標準的窗口最合適的。數組的大小本身並不足以知道元素的哪一側,所以我用簡單的值類包裝起來。

這是我一起去的解決方案。對於更大的流,它絕對不是一個好的解決方案,因爲它會阻止首先讀取整個可觀察對象,對於某些使用情況(在我的情況下,它可以)顯然可能不會。

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來完成這樣的任務? –