Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's difference between "reduce" and "scan"

Tags:

I'm studying RXJS and stuck with the problem: the same code with operators "reduce" and "scan" works in different ways, but I think that must return equal result. Example below. Please help.

const txtElement1 = document.getElementById('txt1'); const txtElement2 = document.getElementById('txt2'); const txtElement3 = document.getElementById('txt3');  // function return Observable function get(array, initValue) {   return Rx.Observable.create(observer => {     let timer = initValue;      array.forEach(item => {       setTimeout(() => observer.next(item), timer);       timer += 1000;     });   }); }  // 1) don't work with "reduce" var stream1$ = get(['John', 'Ann', 'Bob'])   .reduce(function(acc, x) {     return acc + ` ${x}`;   }, 'first - ');  stream1$.subscribe(text => txtElement1.innerHTML = text);  // 2)  the same code, but with "scan" - working var stream2$ = get(['John', 'Ann', 'Bob'])   .scan(function(acc, x) {     return acc + ` ${x}`;   }, 'second - ');  stream2$.subscribe(text => txtElement2.innerHTML = text);  // 3)  and the simple Observable with "reduce" - working var stream3$ = Rx.Observable.from(['John', 'Ann', 'Bob'])   .reduce(function(acc, x) {     return acc + ` ${x}`;   }, 'third - ');  stream3$.subscribe(text => txtElement3.innerHTML = text); 
like image 834
Alex Ovchinkin Avatar asked Jul 27 '17 12:07

Alex Ovchinkin


2 Answers

From RxJS documentation,

Scan

apply a function to each item emitted by an Observable, sequentially, and emit each successive value

enter image description here

Reduce

apply a function to each item emitted by an Observable, sequentially, and emit the final value

enter image description here

Example codes

Scan

var source = Rx.Observable.range(1, 3) .scan(     function (acc, x) {         return acc + x;     });  var subscription = source.subscribe(     function (x) { console.log('Next: ' + x); },     function (err) { console.log('Error: ' + err); },     function () { console.log('Completed'); }); 

For each value emitted by the Observable, scan emits corresponding output sequentially, So the Output will have 3 values for range 1 to 3, as follows

Output Next: 1 Next: 3 Next: 6 Completed 

Reduce

var source = Rx.Observable.range(1, 3)     .reduce(function (acc, x) {         return acc * x;     }, 1)  var subscription = source.subscribe(     function (x) { console.log('Next: ' + x); },     function (err) { console.log('Error: ' + err); },     function () { console.log('Completed'); }); 

Reduce function reduces the values from observables to a single value (final result) and emit. So the output will be as follows,

Next: 6 Completed 
like image 129
Mohammed Safeer Avatar answered Oct 05 '22 08:10

Mohammed Safeer


there almost the same but scan emits each iteration. and reduce just emits a final results. i like scan when i want to actually see what reduce is doing. so sometimesi . use reduce and i cant visualize what reduce is actually doing. in this case i simple swap out reduce for scan since it will emit on each iteration. this way i can put in a log statement and see the results for each iteration.

like image 32
j2emanue Avatar answered Oct 05 '22 08:10

j2emanue