我想实现两个有限的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);
    })
  }
}


这一切都未经测试,但希望它能使您朝正确的方向发展。

07-25 21:48