Javascript 为什么在订阅产生值后调用max和min?
我有一个对象集合,在处理集合中的任何项目之前,我需要知道其数量范围。我提出了与下面类似的代码,它似乎给出了正确的答案:Javascript 为什么在订阅产生值后调用max和min?,javascript,rxjs,Javascript,Rxjs,我有一个对象集合,在处理集合中的任何项目之前,我需要知道其数量范围。我提出了与下面类似的代码,它似乎给出了正确的答案: 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
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);
});
但我对幕后发生的事情有点困惑。当第一个项目被提交给subscribe方法时,comparer函数给出了正确的答案,但是在项目之间继续调用它们
这是一本书。我做错什么了吗?有没有更好的,更Rx-y的方法来做到这一点?我所期望的是首先计算max和min值,然后调用subscription函数,而不调用max或min
编辑:看起来行为可能是它正在不断地与尚未输出的内容进行重新比较,这部分解释了为什么我会看到这种行为。我只是不明白它为什么这样做(以及如何停止):你的第二个例子是正确的。我建议使用
when()
和以及然后执行,但是,它应该具有相同的行为,但是您可以更清楚地传达您的意图,并且不必担心同步问题
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};
});
下面是一个例子
由于这不是计算最小值的最有效方法,因为您要在数组中运行两次,因此可以通过使用reduce()
创建自己的最小值操作符来进一步优化
Rx.Observable.prototype.minMax=函数(比较器){
var source=这个,
c=比较器| |函数(x,y){
返回x-y;
};
返回源.reduce(函数(seed,x){
如果(c(x,seed.min)<0(seed.min=x);
如果(c(x,seed.max)>0(seed.max=x);
返回种子;
},{min:Number.MAX_值,MAX:Number.min_值});
};
Hmm,因为您使用的是flatMap
,zip
操作符的调用次数将是集合中元素数的倍。我不知道您想如何使用此代码,但也许combinelateest
可以完成此工作?我们正在进行一个可视化,它将获取每个项目,并根据其在整个集合中的位置对其进行分类,以便在传递值的同时传递最小值/最大值。我对您的示例进行了一些调整,以使其以这种方式工作,但仍不确定这是否比计算RX链的最小/最大值,然后将其传递进来“更好”。谢谢你,这也解决了我所关心的一个问题,那就是在整个列表中迭代两次,分别得到最大值和最小值。看起来不错!
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 });
};