I have this expression:
var s2 = of(6, 16, 26).pipe(
map(v1=>of(5, 15, 25).pipe(
map(v2=>[v1,v2])
)),
combineLatestAll());
s2.subscribe(console.log)
... and s2 is an of type Observable<number[][]>as I want it.
Can I convert the following expression in a similar way to Observable<number[][][]> (instead of it being an Observable<Observable<number[]>[]>):
var r2 = of(5, 15, 25).pipe(
map(v1=>of(6, 16, 26).pipe(
map(v2=>of(7, 17, 27).pipe(
map(v3 => [v1,v2,v3])
)))),
combineLatestAll());
//Print the output:
r2.subscribe(e1 => {
e1.forEach(e2 => {
e2.subscribe(e3 => {
console.log(e3);
});
})
});
I can't get my head around it. Any help appreciated.
Solution suggested by Ruth:
let s3: Observable<number> = of(5, 15, 25);
let s4: Observable<number> = of(6, 16, 26);
let s5: Observable<number> = of(7, 17, 27);
const r1 = s3.pipe(
map((v3: number) =>
s4.pipe(
mergeMap((v4: number) =>
s5.pipe(
reduce((acc: number[][], v5: number, i5: number) => {
acc[i5] = [v3, v4, v5];
return acc;
}, [])
)
)
)
),
combineLatestAll()//reduce((acc: number[][], curr: number[][]) => [...acc, curr], [])
)
r1.subscribe(console.log);
It seems like you could use just toArray() operator but it's pretty hard to wrap my head around the nested calls so I'm not sure this is what you wanted :):
var r2 = of(5, 15, 25).pipe(
map(v1=>of(6, 16, 26).pipe(
map(v2=>of(7, 17, 27).pipe(
map(v3 => [v1,v2,v3]),
toArray(),
)))),
combineLatestAll());
Live demo: https://stackblitz.com/edit/rxjs-veofem?devtoolsheight=60
... or if you want to avoid the nested Observable you'll need mergeMap:
var r2 = of(5, 15, 25).pipe(
map(v1=>of(6, 16, 26).pipe(
mergeMap(v2=>of(7, 17, 27).pipe(
map(v3 => [v1,v2,v3]),
toArray(),
)))),
combineLatestAll());
r2.subscribe(e1 => {
e1.forEach(e2 => {
console.log(e2);
})
});
Live demo: https://stackblitz.com/edit/rxjs-riquzh?devtoolsheight=60
something like below, your combineLatestAll() only works for the first level map that's why it returns the wrong result. I prefer mannually control the execution of observable with mergeMap,switchMap etc
of(5, 15, 25)
.pipe(
mergeMap((v1) =>
of(6, 16, 26).pipe(
mergeMap((v2) => of(7, 17, 27).pipe(map((v3) => [v1, v2, v3])
))
)
)
)
.subscribe(console.log);
Based on your comment, IMO this is rather a relatively difficult exercise to learn RxJS. Nevertheless, in addition to the solution provided by @martin, you could try to use the reduce with concatMap operator to manually set the array.
Note that reduce((acc, curr) => [...acc, curr], []) is synonymous to the toArray() operator.
const { of } = rxjs;
const { concatMap, reduce } = rxjs.operators;
const jsonEditor = document.getElementById('json-editor');
const textContainer = document.getElementById('text-container');
const options = {};
const editor = new JSONEditor(jsonEditor, options);
let s3 = of(5, 15, 25);
let s4 = of(6, 16, 26);
let s5 = of(7, 17, 27);
s3.pipe(
concatMap((v3) =>
s4.pipe(
concatMap((v4) =>
s5.pipe(
reduce((acc, v5, i5) => {
acc[i5] = [v3, v4, v5];
return acc;
}, [])
)
)
)
),
reduce((acc, curr) => [...acc, curr], [])
).subscribe({
next: (response) => editor.set(response),
error: (error) => textContainer.innerHTML = error
});
<link href="https://unpkg.com/jsoneditor@9.4.1/dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.5/rxjs.umd.min.js"></script>
<script src="https://unpkg.com/jsoneditor@9.4.1/dist/jsoneditor-minimalist.min.js"></script>
<div id="json-editor" style="width: 100%; height: 100%;"></div>
<span id="text-container"></span>
import { of, Observable } from 'rxjs';
import { concatMap, reduce } from 'rxjs';
let s3: Observable<number> = of(5, 15, 25);
let s4: Observable<number> = of(6, 16, 26);
let s5: Observable<number> = of(7, 17, 27);
s3.pipe(
concatMap((v3: number) =>
s4.pipe(
concatMap((v4: number) =>
s5.pipe(
reduce((acc: number[][], v5: number, i5: number) => {
acc[i5] = [v3, v4, v5];
return acc;
}, [])
)
)
)
),
reduce((acc: number[][], curr: number[][]) => [...acc, curr], [])
).subscribe(console.log);
Working example: Stackblitz