android - Rxjava zip运算符通过检查第一个Observable的数据来过滤第二个Observable android

标签 android filter rx-java rx-android

我正在使用 .zip 运算符组合 2 个 API 调用

我想要什么

我想根据 1st Observable 中的一些 ids2nd Observable 获取过滤值

例如

1st Observable 返回类似(示例数据)的数据

"categories": [
{
            "category": "1",
            "category_name": "Wedding Venues",
            "category_photo_url": "http://www.marriager.com/uploads/album/0463373001465466151-0463467001465466151.jpeg",
            "category_type_id": "1",

2nd Observable 返回如下数据:

"data": [
        {
            "cat_id": "1",
            "category_name": "Wedding Venues",
            "status": "1",
            "order_id": "1",
            "category_type_id": "1"
        },

我想过滤我的第二个 Observable 数据,仅返回与第一个 Observable 中的 category_type_id 匹配的值

我的代码

Observable obsService = retrofitService.loadService(getSharedPref().getVendorId());
Observable obsCategory = retrofitService.loadCategory();

Observable<ServiceAndCategory> obsCombined = Observable.zip(obsService.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()), obsCategory.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()), new Func2<ServiceModel, CategoryModel, ServiceAndCategory>() {
            @Override
            public ServiceAndCategory call(ServiceModel serviceModel, CategoryModel categoryModel) {
                return new ServiceAndCategory(serviceModel, categoryModel);
            }
        });
        obsCombined.observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io());

        obsCombined.subscribe(new Subscriber<ServiceAndCategory>() {
            @Override
            public void onCompleted() {


            }

            @Override
            public void onError(Throwable e) {
                if (e instanceof UnknownHostException || e instanceof ConnectException) {
                    mPresenter.onNetworkError();
                } else if (e instanceof SocketTimeoutException) {
                    mPresenter.onTimeOutError();
                } else {
                    mPresenter.onServerError();
                }
            }

            @Override
            public void onNext(ServiceAndCategory model) {

                mPresenter.onSuccess(model);
            }
        });

编辑

基本上我想应用以下逻辑

this.categoryList = combinedModel.categoryModel.getData();
        serviceList = combinedModel.serviceModel.getData().getCategories();

        for (int i = 0; i < serviceList.size(); i++) {

            for (int j = 0; j < categoryList.size(); j++) {

                if (!serviceList.get(i).getCategoryTypeId().equals(categoryList.get(j).getCategoryTypeId())) {

                    categoryList.remove(j);

                }

            }

        }

最佳答案

您可以使用 map 和列表通过响应式(Reactive)方法应用此过滤,首先将所有类别收集到 map ,将所有服务收集到列表,将它们压缩在一起,然后根据类别 map 过滤服务列表:

Observable<HashMap<Integer, CategoryData>> categoriesMapObservable =
        obsCategory
                .flatMapIterable(CategoryModel::getData)
                .reduce(new HashMap<>(),
                        (map, categoryData) -> {
                            map.put(categoryData.getCategoryTypeId(), categoryData);
                            return map;
                        }
                );

Observable<List<ServiceData>> serviceListObservable = obsService
        .map(ServiceModel::getData);

Observable obsCombined =
        Observable.zip(
                categoriesMapObservable
                        .subscribeOn(Schedulers.io()),
                serviceListObservable
                        .subscribeOn(Schedulers.io()),
                Pair::new
        )
                .flatMap(hashMapListPair -> {
                    HashMap<Integer, CategoryData> categoriesMap = hashMapListPair.first;
                    return Observable.from(hashMapListPair.second)
                            .filter(serviceData -> categoriesMap.containsKey(serviceData.getCategoryTypeId()))
                                .toList();
                    }, (hashMapListPair, serviceDataList) -> new Pair<>(hashMapListPair.first.values(), serviceDataList));

输出结果取决于你,这里我在最后应用一个flatMap()选择器,它将创建一对CategoryData集合和一个过滤列表ServiceData,您当然可以创建所需的任何自定义对象。

我不确定你是否从中获得了很多,从复杂性的角度来看,它似乎更有效,假设 HashMap 是 O(1),其中类别是 N,服务是 M,你这里有 N + M (N构造 map ,M 迭代列表并查询 map ),而你的天真的实现将是 N x M。

至于代码复杂性,我不确定是否值得,您可以在 zip 末尾应用逻辑进行过滤,或者使用一些可能更有效地进行过滤的库。

P.S observerOn(AndroidSchedulers.mainThread() 是不必要的,所以我删除了它。

关于android - Rxjava zip运算符通过检查第一个Observable的数据来过滤第二个Observable android,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44535922/

相关文章:

javascript - jquery 如果输入包含来自 array-child friendly global chat 的短语

ios - RxSwift flatMapLatest 无需处理以前的可观察值

java - 从 VS2010 过渡到 Eclipse IDE for Android/Java dev

android - 为什么android studio允许我编译时出现语法错误

javascript - 如何使用Lodash _.filter过滤多条件?

javascript - 脚本438 : Object doesn't support property or method 'filter' IE10

android - 如何仅在退出应用程序时结束服务?

android - 创建一个中间带有图标的按钮

java - 如何动态更新 RX Observable?

rx-java - 如何使用RxJava协调可完成执行的列表?