Edan Bainglass
Edan Bainglass

Reputation: 33

Convert observables of arrays to an array of objects

I have two observables of arrays (settings, mappings). I need to generate from these an object[] array, where each object is of the form { setting, mapping } in order.

I've attempted to forkJoin the two observables, but I'm not sure how to proceed. The method is in a service and should return Observable<object[]>.

I was thinking I need to somehow zip and map the result of forkJoin to the objects, but I can't seem to get this done.

RXJS docs are not particularly helpful, or perhaps I don't know how to read them correctly. Any suggestions are appreciated in advance.

Update

I was able to get it to work with the following implementation:

return forkJoin([settings, mappings]).pipe(
    map(([settings, mappings]) => {
        const cards = settings.map((setting, index) => {
            const card: Card = {
                settings: setting,
                apps: mappings[index].appInformation,
            };
            return card;
        });
        return cards;
    })
);

I am too new to web programming to analyze the efficiency of my implementation. If there is a better way... please...

Upvotes: 0

Views: 866

Answers (1)

MoxxiManagarm
MoxxiManagarm

Reputation: 9134

I was thinking I need to somehow zip and map the result

Not right but also not wrong. Zipping observables zips emisionwise, while you only get one emision with an array.

You have 2 choices:

You transform each observable to an observable emitting each array element and zip the transformed observables.

import { from, Observable, of, switchMap, zip } from 'rxjs'

const emitArrayOneTime1: Observable<number[]> = of([1, 2, 3, 4, 5]);
const emitArrayOneTime2: Observable<string[]> = of(['a', 'b', 'c', 'd', 'e']);

const emitArrayElements1 = emitArrayOneTime1.pipe(switchMap(arr => of(...arr)));
const emitArrayElements2 = emitArrayOneTime2.pipe(switchMap(arr => of(...arr)));

zip([emitArrayElements1, emitArrayElements2]).subscribe(console.log)

Or

You forkJoin both emits and zip the array results. In following exmaple I simplify the code by using lodash zip

import { forkJoin, Observable, of, map } from 'rxjs'
import { zip } from 'lodash';

const emitArrayOneTime1: Observable<number[]> = of([1, 2, 3, 4, 5]);
const emitArrayOneTime2: Observable<string[]> = of(['a', 'b', 'c', 'd', 'e']);

forkJoin([emitArrayOneTime1, emitArrayOneTime2]).pipe(
  map(([arr1, arr2]) => zip(arr1, arr2))
).subscribe(console.log)

Upvotes: 1

Related Questions