我想实现两个有限的Observable序列的relative complement,这是到目前为止我得到的最好的结果:
function relativeComplement (setA, setB, cmp) {
return setA.concatMap(objA =>
setB
.reduce((acc, cur) => {
if (cmp(objA, cur)) {
return {val: objA, skip:true}
}
return acc
}, {val: objA, skip: false})
.filter(obj => !obj.skip)
.map(obj => obj.val)
)
}
该示例有效,但有两个我无法克服的问题。首先,我想使用scan而不是reduce,因为我知道如果已经将skip设置为true,那么继续执行序列是没有意义的。
第二个问题是最困扰我的问题。
如果setB是一个冷的可观察到的东西,它将“构造它”,或对其附加setA.length次数产生任何副作用。
这是显示问题的jsbin
所以我有两个问题。
您是否看到另一种方法来实现克服这两个问题的相对互补?
我可以缓存setB的结果,以便它不重播构造和副作用吗?
注意:我正在使用RxJs 5 alpha,并且在可观察的原型中没有重播方法
最佳答案
如果继续将可观察对象转换为数组,并假设您具有函数relativeComplementArray
:
function relativeComplement (setA, setB, cmp) {
return Rx.Observable.forkJoin(setA.toArray(), setB.toArray(), function (arrayA, arrayB){
return relativeComplementArray(arrayA, arrayB, cmp);
})
}
对于具有
replay
功能的版本,在函数中使用它会更加复杂,因为您不需要在setB
上工作,而在setB.shareReplay()
上工作。我建议您使用咖喱函数。
function relativeComplement ( setB, cmp ) {
var sharedSetB = setB.shareReplay();
return function ( setA ) {
return Rx.Observable.forkJoin(setA.toArray(), sharedSetB.toArray(), function ( arrayA, arrayB ) {
return relativeComplementArray(arrayA, arrayB, cmp);
})
}
}
这一切都未经测试,但希望它能使您朝正确的方向发展。