Сканирование
применяет функцию к каждому элементу, испускаемому Observable, последовательно, и испускает каждое последующее значение
Оператор Scan применяет функцию к первому элементу, испускаемому исходным Observable, и затем испускает результат этой функции как собственное первое испускание. Он также передаёт результат функции обратно в функцию вместе со вторым элементом, испускаемым исходным Observable, для генерации его второго испускания. Он продолжает передавать собственные последующие испускания вместе с последующими испусканиями из исходного Observable, чтобы создать остальную последовательность.
Такой оператор иногда называется «аккумулятором» в других контекстах.
См. также
Информация, специфичная для языка
RxGroovy scan
RxGroovy реализует этот оператор как scan. Например, следующий код берёт Observable, который испускает последовательную последовательность целых чисел n, начиная с 1, и преобразует его посредством scan, в Observable, который испускает первые n треугольных чисел:
Пример кода
numbers = Observable.from([1, 2, 3, 4, 5]);
numbers.scan({ a, b -> a+b }).subscribe(
{ println(it); }, // onNext
{ println("Error: " + it.getMessage()); }, // onError
{ println("Sequence complete"); } // onCompleted
);
1 3 6 10 15 Sequence complete
- Javadoc:
scan(Func2)
Также существует вариант scan, которому вы можете передать значение начального состояния для передачи функции-аккумулятора в первый раз при вызове (для первого испускания из исходного Observable) вместо результата отсутствующего предыдущего вызова функции-аккумулятора. Обратите внимание, что если вы используете этот вариант, scan будет испускать это начальное состояние как собственное начальное испускание. Также обратите внимание, что передача начального состояния null не эквивалентна передаче вообще без начального состояния. Начальное состояние null — это допустимый вид начального состояния.
- Javadoc:
scan(R,Func2)
Этот оператор по умолчанию не работает с каким-либо конкретным Планировщиком.
RxJava 1․x scan
RxJava реализует этот оператор как scan.
Пример кода
Observable.just(1, 2, 3, 4, 5)
.scan(new Func2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer sum, Integer item) {
return sum + item;
}
}).subscribe(new Subscriber<Integer>() {
@Override
public void onNext(Integer item) {
System.out.println("Next: " + item);
}
@Override
public void onError(Throwable error) {
System.err.println("Error: " + error.getMessage());
}
@Override
public void onCompleted() {
System.out.println("Sequence complete.");
}
});
Next: 1 Next: 3 Next: 6 Next: 10 Next: 15 Sequence complete.
- Javadoc:
scan(Func2)
Также существует вариант scan, которому вы можете передать значение начального состояния для передачи функции-аккумулятора в первый раз при вызове (для первого испускания из исходного Observable) вместо результата отсутствующего предыдущего вызова функции-аккумулятора. Обратите внимание, что если вы используете этот вариант, scan будет испускать это начальное состояние как собственное начальное испускание. Также обратите внимание, что передача начального состояния null не эквивалентна передаче вообще без начального состояния. Начальное состояние null — это допустимый вид начального состояния.
- Javadoc:
scan(R,Func2)
Этот оператор по умолчанию не работает с каким-либо конкретным Планировщиком.
RxJS expand scan
RxJS реализует оператор 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'); });
Next: 1 Next: 3 Next: 6 Completed
Вы можете необязательно передать scan значение начального состояния в качестве дополнительного параметра. scan передаст это значение начального состояния функции-аккумулятору в первый раз при вызове (для первого испускания из исходного Observable) вместо результата отсутствующего предыдущего вызова функции-аккумулятора.
Пример кода
var source = Rx.Observable.range(1, 3)
.scan( 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'); });
Next: 1 Next: 2 Next: 6 Completed
scan содержится в каждом из следующих распределений:
rx.jsrx.all.jsrx.all.compat.jsrx.compat.jsrx.lite.jsrx.lite.compat.js
RxJS также реализует оператор expand, который несколько похож. Вместо применения функции к предыдущему возвращаемому значению функции в сочетании со следующим элементом, испускаемым исходным Observable, таким образом, что количество элементов, которое он испускает, равно количеству элементов, испускаемых исходным Observable, expand просто передаёт возвращаемое значение функции обратно в функцию без учёта будущих испусканий из Observable, таким образом, что он просто будет продолжать создавать новые значения своим собственным темпом.
Пример кода
var source = Rx.Observable.return(42)
.expand(function (x) { return Rx.Observable.return(42 + x); })
.take(5);
var subscription = source.subscribe(
function (x) { console.log('Next: ' + x); },
function (err) { console.log('Error: ' + err); },
function () { console.log('Completed'); });
Next: 42 Next: 84 Next: 126 Next: 168 Next: 210 Completed
expand содержится в каждом из следующих распределений:
rx.all.jsrx.all.compat.jsrx.experimental.js
expand требует одного из следующих распределений:
rx.jsrx.compat.jsrx.lite.jsrx.lite.compat.js
RxPHP scan
RxPHP реализует этот оператор как scan.
Применяет функцию-аккумулятор к последовательности Observable и возвращает каждый промежуточный результат. Необязательное начальное значение используется как начальное значение аккумулятора.
Пример кода
//from https://github.com/ReactiveX/RxPHP/blob/master/demo/scan/scan.php
//Without a seed
$source = Rx\Observable::range(1, 3);
$subscription = $source
->scan(function ($acc, $x) {
return $acc + $x;
})
->subscribe($createStdoutObserver());
Next value: 1 Next value: 3 Next value: 6 Complete!
//from https://github.com/ReactiveX/RxPHP/blob/master/demo/scan/scan-with-seed.php
//With a seed
$source = Rx\Observable::range(1, 3);
$subscription = $source
->scan(function ($acc, $x) {
return $acc * $x;
}, 1)
->subscribe($createStdoutObserver());
Next value: 1 Next value: 2 Next value: 6 Complete!
© ReactiveX contributors
Licensed under the Apache License 2.0.
http://reactivex.io/documentation/operators/scan.html