我有一组对象,在处理集合中的任何项目之前,我需要知道数字范围是什么。我想出了类似于下面的代码,似乎给出了正确的答案:
var arr = Rx.Observable.fromArray([10,-10,4,-5,20,4,7]),
//In actual code this is an array of objects, so have a custom compare function
numberComparer = function(a,b) { return a-b; };
//In actual code this is prefixed by a filter and mapping operation
arr.flatMap(function(x) {
return Rx.Observable.zip(
arr.max(numberComparer),
arr.min(numberComparer),
function(max, min) {
return {
stats: {max: max, min: min},
item: x
};
}
);
})
.subscribe(function(item) {
DoStuffWithItem(item.item, item.stats);
});
但我对幕后发生的事情感到有些困惑。当第一项产生于订阅方法时,比较器函数给出了正确的答案,但随后它们继续在项目产量之间被调用。
这是JSBin showing what I mean。我在这里做错了吗?是否有更好,更Rx-y的方式来做到这一点?我期望发生的是首先计算最大值和最小值,然后调用订阅函数而不调用max或min。
编辑:看起来行为可能是因为它已经输出的内容不断重新比较,这部分解释了为什么我会看到这种行为。我只是不明白它为什么这样做(以及如何让它停止):)
答案 0 :(得分:1)
你的第二个例子是在正确的轨道上。我建议使用when()
and
和thenDo
,但它应该具有相同的行为,但您可以更清楚地传达您的意图,而您不必担心同步
var minMax = Rx.Observable.when(
filteredArray.max().and(filteredArray.min())
.thenDo(function(x, y) {
return { max : x, min : y};
}));
minMax.flatMap(function() {
return filteredArray;
}, function(stats, x) {
return {stats : stats, value : x};
});
以下是该示例的modifed version。
由于这不是计算minMax的最有效方法,因为您在阵列中运行两次,因此可以通过使用reduce()
创建自己的minMax运算符来进一步优化。
Rx.Observable.prototype.minMax = function(comparer) {
var source = this,
c = comparer || function(x, y) {
return x - y;
};
return source.reduce(function(seed, x) {
if (c(x, seed.min) < 0) (seed.min = x);
if (c(x, seed.max) > 0) (seed.max = x);
return seed;
}, {min : Number.MAX_VALUE, max : Number.MIN_VALUE });
};