33

我有两个可观察的:

  1. 表示复选框输入列表的可观察对象。
  2. 一个表示来自服务器的事件流的可观察对象。

我想使用第一个值过滤第二个 observable。

从服务器接收到的值包含一个tag属性,该属性对应于复选框列表中的值。由上述两者组合产生的 observable 只会产生来自服务器的值,该服务器的tag属性包含在选中的复选框中。

4

4 回答 4

40

您可以使用withLatestFrom. 在此处输入图像描述.

source.withLatestFrom(checkboxes, (data, checkbox) => ({data, checkbox}))
  .filter(({data, checkbox}) => ...)

这里,checkboxes是一个表示复选框输入列表的可观察对象。source是一个表示来自服务器的事件流的可观察对象。在过滤器功能中,您可以检查数据是否与复选框设置相比有效并让它通过。

checkboxes请注意,在流可以发出任何东西之前发出至少 1 个值是很重要的。

附言。关于其他答案,即使源是的,此解决方案也有效。

于 2016-08-24T22:03:17.220 回答
6

为了使用流 B 的值过滤流 A,您需要观察流 B 并使用最新的值来过滤流 A。

用于switch()将 B observable 转换为 observable 从 A observable 产生值。

checkedInputValuesSource
    .map(function (options) {
        return dataSource
            .filter(function (value) {
                return options.indexOf(value) !== -1;
            });
    })
    .switch()
    .subscribe(function (x) {
        console.log('out: ' + x);
    });

使用switch()假设这dataSource是一个热门的 observable

interval()用于生成虚拟数据的示例:

var input,
    checkedInputValuesSource,
    dataSource;

input = document.querySelectorAll('input');

// Generate source describing the current filter.
checkedInputValuesSource = Rx.Observable
    .fromEvent(input, 'change')
    .map(function () {
        var inputs = document.querySelectorAll('input'),
            checkedInputValues = [];
        
        [].forEach.call(inputs, function (e) {
            if (e.checked) {
                checkedInputValues.push(e.value);
            }
        });
        
        return checkedInputValues;
    })
    .startWith([]);

// Generate random data source (hot).
dataSource = Rx.Observable
    .interval(500)
    .map(function () {
        var options = ['a', 'b', 'c'];
    
        return options[Math.floor(Math.floor(Math.random() * options.length))];
    })
    .do(function (x) {
        console.log('in: ' + x);
    })
    .share();

checkedInputValuesSource
    .map(function (options) {
        return dataSource
            .filter(function (value) {
                return options.indexOf(value) !== -1;
            });
    })
    .switch()
    .subscribe(function (x) {
        console.log('out: ' + x);
    });
<script src='https://rawgit.com/Reactive-Extensions/RxJS/v.2.5.3/dist/rx.all.js'></script>

<input type='checkbox' value='a'>
<input type='checkbox' value='b'>
<input type='checkbox' value='c'>

此示例将产生类似于以下内容的输出:

in: c
in: a
out: a
in: b
in: c
out: a
in: b
in: a

其中in反映了所有生成的输入和b通过过滤器的数据。通过检查复选框输入来调整过滤器,这些输入反映值“a”、“b”和“c”。

于 2015-08-03T06:10:57.030 回答
2

显然,我需要的是select,filterswitchLatest. 我写了一个小测试用例来证明这一点:https ://gist.github.com/igstan/d5b8db7b43f49dd87382#file-observable-filter-observable-js-L36-L45

于 2013-07-19T12:33:50.767 回答
0

扩展@Dorus的答案......在Kotlin中,您可以这样做:

val observable: Observable<Data> = ...
val filter: Observable<Checkbox> = ...
val filtered: Observable<Data> =
        observable.filterWithLatestFrom(filter) { checkbox -> checkbox.isSelected }

使用扩展功能:

/**
 * Return an [Observable] with type [T1] that is filtered using the last event emitted by the [other] observable.
 */
fun <T1 : Any, T2 : Any> Observable<T1>.filterWithLatestFrom(other: Observable<T2>, filterFunction: (T2) -> Boolean)
: Observable<T1> {
    return this.withLatestFrom(other) { obs1, obs2 -> Pair(obs1, obs2) }
        .filter { (_, obs2) -> filterFunction.invoke(obs2) }
        .map { (obs1, _) -> obs1}
}
于 2021-02-05T12:42:53.037 回答