2017-04-10 47 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来完成这样的任务? –