Reputation: 43785
The following code produces the result I desire:
// output 1,2,3,4,5,etc
var input$ = Rx.Observable.interval(500).map((v, idx) => idx+1);
var inputEveryOtherOdd$ = input$
// filter even numbers
.filter(v => v % 2)
.map(x => x) // workaround to fix the index (read below)
// filter every other remaining number (take every other odd number)
.filter((v, idx) => {
console.log(`Value: ${v}, Index: ${idx}`)
return !(idx % 2);
})
.subscribe(function(v) {
output.textContent+= v;
})
;
The log produces:
Value: 1, Index: 0
Value: 3, Index: 1
Value: 5, Index: 2
Value: 7, Index: 3
Value: 9, Index: 4
Each item that passes the first filter has the next index so that the index is incremented by one for each item (0,1,2,3,4,5,etc)
.
What I can't understand is if I remove map
, the second filter receives different idx
values for the same items:
Value: 1, Index: 0
Value: 3, Index: 2
Value: 5, Index: 4
Value: 7, Index: 6
Value: 9, Index: 8
It seems that the values filtered in the first filter are still being considered in the second filter. I can't make any sense of it. The filter function doesn't run for the values, so how can the index be incrementing for items that don't exist? Why does map
make any difference?
I expect chaining two filters together would produce the same result as synchronous filtering and the idx
value would be 0,1,2,3,4,5,etc
in each filter.
var result = [1,2,3,4,5,6,7,8,9]
.filter(v => v % 2)
.filter((v, idx) => !(idx % 2));
I was originally using startWith
in place of map
. It seems like just putting something in between the filters makes the idx
value what I expect.
Upvotes: 0
Views: 89
Reputation: 18663
The problem is ironically a "feature" of the current version (v4) of RxJS.
The filter
operator contains an optimization to detect if it is being used in a "chained" manner, that is, if you have multiple filters in a row. If it is then it will not create a second FilterObservable
but rather will wrap the new filter operation in as part of the existing Observable.
See source code here and here.
As a result, no matter how many filters you chain together you will always receive the same index for all of them.
When you use an operator in between the two filters then it cannot perform the optimization and so the filters will not be merged and you will see different indices.
Upvotes: 1
Reputation: 7947
The indexidx
is the index of the element in the original list, independently of what has been filtered out.
Upvotes: 0