简体   繁体   English

RxJava比较两个observable中的不同项(java 7)

[英]RxJava compare different items from two observables (java 7)

I have two Observables ob1 & ob2 that emit items . 我有两个Observables ob1和ob2发出项目。 If ob1.item is contained in ob2 I want to ignore it. 如果ob1.item包含在ob2中,我想忽略它。

Example : 示例:

ob1 contains A,B,C,D

ob2 contains E,C,B,G,J,O

output : 输出:

ob contains A,D

What is the best way to express this ? 表达这个的最佳方式是什么?

There is a contains operator which returns Observable<Boolean> for whether observable contains given element. 有一个contains运算符,它返回Observable<Boolean> ,表示observable是否包含给定元素。

Observable<Boolean> contains = observable2.contains(string);

What you need is to map all elements from observable1 to those boolean observables 你需要的是将observable1所有元素映射到那些boolean observables

observable1.map(new Func1<String, Observable<Boolean>>() {
    @Override
    public Observable<Boolean> call(final String string) {
        return observable2.contains(string);
    }
})

This would give you Observable<Observable<Boolean>> , but it would be hard to work with this. 这会给你Observable<Observable<Boolean>> ,但是很难用它。 Therefore you concatenate all those boolean observables into one. 因此,您将所有这些布尔可观察量连接成一个。 Luckilly, all you need to do for that is to use concatMap instead of map Luckilly,你需要做的就是使用concatMap而不是map

observable1.concatMap(new Func1<String, Observable<Boolean>>() {
    @Override
    public Observable<Boolean> call(final String string) {
        return observable2.contains(string);
    }
})

Now you have an observable1 that contains your elements and an Observable<Boolean> that contains boolean for whether the element in observable1 is contained in observable2 现在你有一个observable1包含你的元素和一个Observable<Boolean> ,它包含boolean,表示observable1的元素是否包含在observable2

observable1:            A ---- B ---- C ---- D
concatMapObservable:    false  true   true   false

You can easily zip those two observables into an observable which will pass the elements that are not contained in observable2 and replace others with an empty string 您可以轻松地zip这两个可观察到可观察到的,这将传递不包含在元素observable2并用一个空字符串代替他人

[concatMapObservable].zipWith(observable1, new Func2<Boolean, String, String>() {
    @Override
    public String call(final Boolean contains, final String string) {
        return contains ? "" : string;
    }
}

Then you filter the empty strings 然后你过滤空字符串

[zippedObservable].filter(new Func1<String, Boolean>() {
    @Override
    public Boolean call(final String string) {
        return !TextUtils.isEmpty(string);
    }
})

The whole code put together: 整个代码放在一起:

Observable<String> observable1 = Observable.from(new String[]{"A", "B", "C", "D"});
Observable<String> observable2 = Observable.from(new String[]{"E", "C", "B", "G", "J", "O"});

observable1.concatMap(new Func1<String, Observable<Boolean>>() {
    @Override
    public Observable<Boolean> call(final String string) {
        return observable2.contains(string);
    }
}).zipWith(observable1, new Func2<Boolean, String, String>() {
    @Override
    public String call(final Boolean contains, final String string) {
        return contains ? "" : string;
    }
}).filter(new Func1<String, Boolean>() {
    @Override
    public Boolean call(final String string) {
        return !TextUtils.isEmpty(string);
    }
}).subscribe(new Action1<String>() {
    @Override
    public void call(final String string) {
        Log.d("observable:", string);
    }
});

The output of your operation cannot be computed until all items of ob2 have been received, as you cannot tell whether an item in ob1 will be contained in ob2 until you know all items that are part of ob2. 在收到ob2的所有项目之前,无法计算操作的输出,因为在知道所有属于ob2的项目之前,无法确定ob1中的项目是否将包含在ob2中。 As a result, you have to wait for ob2 to complete before you can then filter items from ob1. 因此,您必须等待ob2完成,然后才能从ob1过滤项目。

A possible solution using RxJava2 is below. 使用RxJava2的可能解决方案如下。

    Observable<String> ob1 = Observable.fromArray("A", "B", "C", "D");
    Observable<String> ob2 = Observable.fromArray("E", "C", "B", "G", "J", "O");

    Observable.combineLatest(ob2.toList().toObservable(), ob1, (list, value) -> list.contains(value) ? "" : value)
            .filter(value -> !TextUtils.isEmpty(value))
            .subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(value -> Log.d("foo", "Value: " + value));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM