FlatMap
преобразуйте элементы, излучаемые Observable, в Observable, а затем сгладьте излучения из этих в единое Observable
Оператор FlatMap преобразует Observable, применяя функцию, которую вы задаёте, к каждому элементу, излучаемому исходным Observable, где эта функция возвращает Observable, который сам излучает элементы. FlatMap затем объединяет излучения этих получившихся Observable, излучая эти объединённые результаты как свою собственную последовательность.
Этот метод полезен, например, когда у вас есть Observable, который излучает серию элементов, которые сами имеют члены Observable или иным образом могут быть преобразованы в Observable, так что вы можете создать новое Observable, которое излучает полную коллекцию элементов, излучаемых под-Observable этих элементов.
Обратите внимание, что FlatMap объединяет излучения этих Observable, так что они могут переплетаться.
В нескольких языковых реализациях также есть оператор, который не переплетает излучения преобразованных Observable, а вместо этого излучает эти излучения в строгом порядке, часто называемый ConcatMap или чем-то подобным.
См. также
- Map
- Понимание RxJava: Оператор, Оператор Дэна Лева
- Введение в Rx: SelectMany
- Рекурсивные Observable с RxJava Джона Шнайдера
- Преобразование RxJava Observable: concatMap() против flatMap() Фернандо Сехаса
Языкоспецифичная информация
RxGroovy concatMap flatMap flatMapIterable StringObservable.split switchMap
RxGroovy реализует оператор flatMap.
Пример кода
// this closure is an Observable that emits three numbers
numbers = Observable.from([1, 2, 3]);
// this closure is an Observable that emits two numbers based on what number it is passed
multiples = { n -> Observable.from([ n*2, n*3 ]) };
numbers.flatMap(multiples).subscribe(
{ println(it); }, // onNext
{ println("Error: " + it.getMessage()); }, // onError
{ println("Sequence complete"); } // onCompleted
); 2 3 4 6 6 9 Sequence complete
Обратите внимание, что если любой из отдельных Observables, сопоставленных элементам из исходного Observable с помощью flatMap, прерывается, вызывая onError, то Observable, созданный с помощью flatMap, также немедленно прервется и вызовет onError.
Версия этого варианта оператора (по состоянию на данный момент находится в бета-версии) принимает дополнительный int параметр. Этот параметр устанавливает максимальное количество одновременных подписок, которые flatMap будет пытаться иметь к Observables, которым сопоставляются элементы, выпущенные исходным Observable. Когда это максимальное количество достигнуто, он будет ожидать завершения одного из этих Observables перед подпиской на другой.
- Javadoc:
flatMap(Func1) - Javadoc:
flatMap(Func1,int)
Другая версия оператора flatMap создаёт (и сплющивает) новый Observable для каждого элемента и уведомления из исходного Observable.
Версия этого варианта оператора (по состоянию на данный момент находится в бета-версии) принимает дополнительный int параметр. Этот параметр устанавливает максимальное количество одновременных подписок, которые flatMap будет пытаться иметь к Observables, которым сопоставляются элементы, выпущенные исходным Observable. Когда это максимальное количество достигнуто, он будет ожидать завершения одного из этих Observables перед подпиской на другой.
- Javadoc:
flatMap(Func1,Func1,Func0) - Javadoc:
flatMap(Func1,Func1,Func0,int)
Другая версия комбинирует элементы из исходного Observable с Observable, сгенерированным этими элементами, и выводит эти комбинации.
Версия этого варианта оператора (по состоянию на данный момент находится в бета-версии) принимает дополнительный int параметр. Этот параметр устанавливает максимальное количество одновременных подписок, которые flatMap будет пытаться иметь к Observables, которым сопоставляются элементы, выпущенные исходным Observable. Когда это максимальное количество достигнуто, он будет ожидать завершения одного из этих Observables перед подпиской на другой.
- Javadoc:
flatMap(Func1,Func2) - Javadoc:
flatMap(Func1,Func2,int)
Варианты flatMapIterable объединяют исходные элементы и сгенерированные Iterable вместо исходных элементов и сгенерированных Observables, но в остальном работают аналогично.
- Javadoc:
flatMapIterable(Func1) - Javadoc:
flatMapIterable(Func1,Func2)
Также есть оператор concatMap, который похож на упрощённую версию оператора flatMap, но он конкатенирует, а не объединяет результирующие Observables, чтобы сгенерировать свою последовательность.
- Javadoc:
concatMap(Func1)
RxGroovy также реализует оператор switchMap. Он работает примерно так же, как flatMap, за исключением того, что каждый раз, когда исходный Observable выпускает новый элемент, он отписывается и прекращает отражение Observable, сгенерированного из предыдущего элемента, и начинает отражать только текущий.
- Javadoc:
switchMap(Func1)
В отдельном классе StringObservable (не входит в RxGroovy по умолчанию) также есть оператор split, который преобразует Observable строк в Observable строк, обрабатывает исходную последовательность как поток, разбивает её по указанному разделителю regex и объединяет результаты этого разделения.
См. также
-
Сопоставление пакетов с JSON-документами с помощью оператора
split
RxJava 1․x concatMap flatMap flatMapIterable StringObervable.split switchMap
RxJava реализует оператор flatMap.
Обратите внимание, что если любой из отдельных Observables, сопоставленных элементам из исходного Observable с помощью flatMap, прерывается, вызывая onError, то Observable, созданный с помощью flatMap, также немедленно прервется и вызовет onError.
Версия этого варианта оператора (по состоянию на данный момент находится в бета-версии) принимает дополнительный int параметр. Этот параметр устанавливает максимальное количество одновременных подписок, которые flatMap будет пытаться иметь к Observables, которым сопоставляются элементы, выпущенные исходным Observable. Когда это максимальное количество достигнуто, он будет ожидать завершения одного из этих Observables перед подпиской на другой.
- Javadoc:
flatMap(Func1) - Javadoc:
flatMap(Func1,int)
Другая версия оператора flatMap создаёт (и сплющивает) новый Observable для каждого элемента и уведомления из исходного Observable.
Версия этого варианта оператора (по состоянию на данный момент находится в бета-версии) принимает дополнительный int параметр. Этот параметр устанавливает максимальное количество одновременных подписок, которые flatMap будет пытаться иметь к Observables, которым сопоставляются элементы, выпущенные исходным Observable. Когда это максимальное количество достигнуто, он будет ожидать завершения одного из этих Observables перед подпиской на другой.
- Javadoc:
flatMap(Func1,Func1,Func0) - Javadoc:
flatMap(Func1,Func1,Func0,int)
Другая версия комбинирует элементы из исходного Observable с Observable, сгенерированным этими элементами, и выводит эти комбинации.
Версия этого варианта оператора (по состоянию на данный момент находится в бета-версии) принимает дополнительный int параметр. Этот параметр устанавливает максимальное количество одновременных подписок, которые flatMap будет пытаться иметь к Observables, которым сопоставляются элементы, выпущенные исходным Observable. Когда это максимальное количество достигнуто, он будет ожидать завершения одного из этих Observables перед подпиской на другой.
- Javadoc:
flatMap(Func1,Func2) - Javadoc:
flatMap(Func1,Func2,int)
Варианты flatMapIterable объединяют исходные элементы и сгенерированные Iterable вместо исходных элементов и сгенерированных Observables, но в остальном работают аналогично.
- Javadoc:
flatMapIterable(Func1) - Javadoc:
flatMapIterable(Func1,Func2)
Также есть оператор concatMap, который похож на упрощённую версию оператора flatMap, но он конкатенирует, а не объединяет результирующие Observables, чтобы сгенерировать свою последовательность.
- Javadoc:
concatMap(Func1)
RxJava также реализует оператор switchMap. Он работает примерно так же, как flatMap, за исключением того, что каждый раз, когда исходный Observable выпускает новый элемент, он отписывается и прекращает отражение Observable, сгенерированного из предыдущего элемента, и начинает отражать только текущий.
- Javadoc:
switchMap(Func1)
В отдельном классе StringObservable (не входит в RxJava по умолчанию) также есть оператор split который преобразует Observable строк в Observable строк, обрабатывает исходную последовательность как поток, разбивает её по указанному разделителю regex и объединяет результаты этого разделения.
RxJS concatMap concatMapObserver flatMap flatMapFirst flatMapLatest flatMapObserver flatMapWithMaxConcurrency for forIn manySelect selectConcat selectConcatObserver selectMany selectManyObserver selectSwitch selectSwitchFirst selectWithMatchConcurrent switchMap
RxJS обладает множеством операторов, которые выполняют операции, подобные FlatMap. В RxJS функции, преобразующие элементы, испускаемые исходным Observable, в Observable, обычно принимают в качестве параметров как сам элемент, так и его индекс в последовательности Observable.
RxJS реализует базовый оператор flatMap. У него есть вариант, который позволяет вам применить функцию преобразования (необязательный второй параметр к flatMap) к элементам, испускаемым Observable, сгенерированными для каждого элемента исходного Observable, прежде чем объединить и испустить эти элементы.
flatMap работает так же хорошо, если функция, которую вы предоставляете, преобразует элементы из исходных Observable в Observable, в Promises или в массивы.
«selectMany» — псевдоним для flatMap.
Пример кода
var source = Rx.Observable
.range(1, 2)
.selectMany(function (x) {
return Rx.Observable.range(x, 2);
});
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: 2 Next: 3 Completed
// Using a promise
var source = Rx.Observable.of(1,2,3,4)
.selectMany(function (x, i) {
return Promise.resolve(x + i);
});
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: 5 Next: 7 Completed
// Using an array
Rx.Observable.of(1,2,3)
.flatMap(
function (x, i) { return [x,i]; },
function (x, y, ix, iy) { return x + y + ix + iy; }
);
var subscription = source.subscribe(
function (x) { console.log('Next: ' + x); },
function (err) { console.log('Error: ' + err); },
function () { console.log('Completed'); });
Next: 2 Next: 2 Next: 5 Next: 5 Next: 8 Next: 8 Completed
flatMap можно найти во всех следующих дистрибутивах:
rx.jsrx.all.jsrx.all.compat.jsrx.compat.jsrx.lite.jsrx.lite.compat.js
Оператор flatMapLatest ведет себя очень похоже на стандартный оператор FlatMap, за исключением того, что всякий раз, когда новый элемент испускается исходным Observable, он отписывается от и прекращает отражать Observable, который был сгенерирован из ранее испущенного элемента, и начинает отражать только текущий.
«selectSwitch» — псевдоним для flatMapLatest.
Пример кода
var source = Rx.Observable
.range(1, 2)
.flatMapLatest(function (x) {
return Rx.Observable.range(x, 2);
});
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: 3 Completed
flatMapLatest можно найти во всех следующих дистрибутивах:
rx.jsrx.all.jsrx.all.compat.jsrx.compat.jsrx.lite.jsrx.lite.compat.js
flatMapObserver создает (и сплющивает) новый Observable для каждого элемента и уведомления из исходного Observable. Он принимает различную функцию преобразования для реагирования на уведомления onNext, onError, и onCompleted и для возврата Observable для каждого.
«selectManyObserver» — псевдоним для flatMapObserver.
Пример кода
var source = Rx.Observable.range(1, 3)
.flatMapObserver(
function (x, i) {
return Rx.Observable.repeat(x, i);
},
function (err) {
return Rx.Observable.return(42);
},
function () {
return Rx.Observable.empty();
});
var subscription = source.subscribe(
function (x) { console.log('Next: ' + x); },
function (err) { console.log('Error: ' + err); },
function () { console.log('Completed'); });
Next: 2 Next: 3 Next: 3 Completed
flatMapObserver можно найти во всех следующих дистрибутивах:
rx.jsrx.all.jsrx.all.compat.jsrx.compat.js
Также есть оператор concatMap, который похож на оператор flatMap, но он конкатенирует, а не объединяет, полученные Observable, для генерации собственной последовательности.
Как и в случае с flatMap, concatMap работает так же хорошо, если функция, которую вы предоставляете, преобразует элементы из исходных Observable в Observable, в Promises или в массивы.
«selectConcat» — псевдоним для concatMap.
concatMap можно найти во всех следующих дистрибутивах:
rx.jsrx.all.jsrx.all.compat.jsrx.compat.jsrx.lite.jsrx.lite.compat.js
Оператор for (и его псевдоним forIn) очень похож на concatMap, хотя он имеет обратную гибкость. В то время как concatMap работает с источником Observable и может использовать Observable, Promise или массив в качестве промежуточных элементов для генерации последовательности вывода; for всегда использует Observable в качестве промежуточных элементов, но может работать с источником, который является Observable, Promise или массивом.
concatMap можно найти во всех следующих дистрибутивах:
rx.all.jsrx.all.compat.js-
rx.experimental.js(требует либоrx.js,rx.compat.js,rx.lite.js, илиrx.lite.compat.js)
Также есть оператор concatMapObserver, который похож на оператор flatMapObserver, поскольку он создает Observable для объединения испусканий и терминальных уведомлений исходного Observable, но он конкатенирует, а не объединяет эти полученные Observable для генерации собственной последовательности.
«selectConcatObserver» — псевдоним для concatMapObserver.
concatMapObserver можно найти во всех следующих дистрибутивах:
rx.jsrx.all.jsrx.all.compat.jsrx.compat.js
Оператор manySelect часто описывается как «коммонадическая связка». Если это проясняет ситуацию для вас, то пожалуйста. В противном случае, вот объяснение:
manySelect внутренне преобразует каждый элемент, испускаемый исходным Observable, в Observable, который испускает этот элемент и все элементы, впоследствии испускаемые исходным Observable, в том же порядке. Например, он внутренне преобразует Observable, который испускает числа 1, 2, 3, в три Observable: один, который испускает 1, 2, 3, один, который испускает 2, 3, и один, который испускает 3.
Затем manySelect передает каждое из этих Observable в функцию, которую вы предоставляете, и испускает, как испускания от Observable, который manySelect возвращает, значения возврата от этих вызовов функций.
Таким образом, каждый элемент, испускаемый результатом Observable, является функцией соответствующего элемента в исходном Observable и всех элементов, испускаемых исходным Observable после него.
manySelect можно найти во всех следующих дистрибутивах:
rx.all.jsrx.all.compat.jsrx.experimental.js
manySelect требует одного из следующих дистрибутивов:
rx.jsrx.compat.jsrx.lite.jsrx.lite.compat.js
См. также
RxPHP flatMap flatMapTo selectMany flatMapLatest concatMap concatMapTo
RxPHP реализует этот оператор как flatMap.
Проецирует каждый элемент последовательности observable на последовательность observable и объединяет полученные последовательности observable в одну последовательность observable.
Пример кода
//from https://github.com/ReactiveX/RxPHP/blob/master/demo/flatMap/flatMap.php
$observable = Rx\Observable::range(1, 2);
$selectManyObservable = $observable->flatMap(function ($value) {
return Rx\Observable::range($value, 2);
});
$selectManyObservable->subscribe($stdoutObserver); Next value: 1 Next value: 2 Next value: 2 Next value: 3 Complete!
RxPHP также имеет оператор flatMapTo.
Проецирует каждый элемент исходной observable последовательности на другую observable последовательность и объединяет полученные observable последовательности в одну observable последовательность.
Пример кода
//from https://github.com/ReactiveX/RxPHP/blob/master/demo/concat/concatMapTo.php
$obs = \Rx\Observable::interval(100)
->take(3)
->mapWithIndex(function ($i) {
return $i;
});
$source = Rx\Observable::range(0, 5)
->concatMapTo($obs);
$subscription = $source->subscribe($stdoutObserver); Next value: 0 Next value: 1 Next value: 2 Next value: 3 Next value: 4 Next value: 5 Next value: 6 Next value: 7 Next value: 8 Next value: 9 Next value: 10 Next value: 11 Next value: 12 Next value: 13 Next value: 14 Complete!
RxPHP также имеет оператор selectMany.
Псевдоним для flatMap
RxPHP также имеет оператор flatMapLatest.
Пропускает указанное количество элементов в последовательности observable, а затем возвращает оставшиеся элементы. Преобразует элементы, испускаемые Observable, в Observable, и отображает эти элементы, испускаемые наиболее недавно преобразованным Observable. Оператор flatMapLatest похож на методы flatMap и concatMap, описанные выше, однако, вместо испускания всех элементов, испускаемых всеми Observable, которые оператор генерирует путем преобразования элементов из исходного Observable, flatMapLatest вместо этого испускает элементы из каждого такого преобразованного Observable только до тех пор, пока следующий такой Observable не будет испущен, затем он игнорирует предыдущий и начинает испускать элементы, испускаемые новым.
Пример кода
//from https://github.com/ReactiveX/RxPHP/blob/master/demo/flatMap/flatMapLatest.php
$source = \Rx\Observable::range(1, 3)
->flatMapLatest(function ($x) {
return \Rx\Observable::fromArray([$x . 'a', $x . 'b']);
});
$source->subscribe($stdoutObserver); Next value: 1a Next value: 2a Next value: 3a Next value: 3b Complete!
RxPHP также имеет оператор concatMap.
Проецирует каждый элемент observable последовательности на observable последовательность и конкатенирует полученные observable последовательности в одну observable последовательность.
Пример кода
//from https://github.com/ReactiveX/RxPHP/blob/master/demo/concat/concatMap.php
$source = Rx\Observable::range(0, 5)
->concatMap(function ($x, $i) {
return \Rx\Observable::interval(100)
->take($x)
->map(function () use ($i) {
return $i;
});
});
$subscription = $source->subscribe($stdoutObserver); Next value: 1 Next value: 2 Next value: 2 Next value: 3 Next value: 3 Next value: 3 Next value: 4 Next value: 4 Next value: 4 Next value: 4 Complete!
RxPHP также имеет оператор concatMapTo.
Проецирует каждый элемент исходной observable последовательности на другую observable последовательность и объединяет полученные observable последовательности в одну observable последовательность.
Пример кода
//from https://github.com/ReactiveX/RxPHP/blob/master/demo/concat/concatMapTo.php
$obs = \Rx\Observable::interval(100)
->take(3)
->mapWithIndex(function ($i) {
return $i;
});
$source = Rx\Observable::range(0, 5)
->concatMapTo($obs);
$subscription = $source->subscribe($stdoutObserver); Next value: 0 Next value: 1 Next value: 2 Next value: 3 Next value: 4 Next value: 5 Next value: 6 Next value: 7 Next value: 8 Next value: 9 Next value: 10 Next value: 11 Next value: 12 Next value: 13 Next value: 14 Complete!
© ReactiveX contributors
Licensed under the Apache License 2.0.
http://reactivex.io/documentation/operators/flatmap.html