Search code examples
arraysangularreactive-programmingrxjs6rxjs-observables

How to combine two arrays into a single array using RxJs where 2nd array's each element will be assigned to first arrays each object property?


I have two interfaces, they are Team and Company

public interface Team {
  id: number;
  name: string;
  companyId: number;
}

public interface Company {
  id: number;
  name: string;
}

This is the sample data:

"companies": [
    {
      "id": 3,
      "name": "XSoftware",
      "location": "Nagar"
    },
    {
      "id": 5,
      "name": "Google",
      "location": "Seattle"
    },
    {
      "id": 7,
      "name": "YS",
      "location": "Dhanmondi"
    },
    {
      "id": 8,
      "name": "Amazon",
      "location": "Seattle DC"
    },
    {
      "name": "ToTD",
      "location": "Pink City",
      "id": 10
    }
]
"teams": [
    {
      "id": 1,
      "name": "Team X",
      "expertise": "Java",
      "companyId": 3
    },
    {
      "id": 2,
      "name": "Team Y",
      "expertise": "Angular",
      "companyId": 3
    },
    {
      "id": 3,
      "name": "Team Z",
      "expertise": "Spring Boot",
      "companyId": 8
    },
    {
      "id": 4,
      "name": "Team M",
      "expertise": "Node Js",
      "companyId": 5
    }
]

So I want to assign company as property to each team based on companyId. Like this:

"teams": [
    {
      "id": 1,
      "name": "Team X",
      "expertise": "Java",
      "companyId": 3,
      "company": {
         "id": 3,
          "name": "XSoftware",
          "location": "Nagar"
       }
    },
    {
      "id": 2,
      "name": "Team Y",
      "expertise": "Angular",
      "companyId": 3,
      "company": {
         "id": 3,
          "name": "XSoftware",
          "location": "Nagar"
       }
    },
    {
      "id": 3,
      "name": "Team Z",
      "expertise": "Spring Boot",
      "companyId": 8,
      "company": {
         "id": 8,
         "name": "Amazon",
         "location": "Seattle DC"
       }
    },
    {
      "id": 4,
      "name": "Team M",
      "expertise": "Node Js",
      "companyId": 5,
      "company": {
         "id": 5,
         "name": "Google",
         "location": "Seattle"
       }
    }
]

So how can I achieve this using RxJs. I have two observables that return Observable of Team[] and Company[] respectively.

const teams$: Observable<Team[]> = this.httpClient.get<Team[]>('/teams');
const companies$: Observable<Company[]> = this.httpClient.get<Company[]>('/companies');

So, How to do this? I know it can be done in imperative way (by using loops, if-else etc), but I want to do this in reactive way by only using reactive operators, observers.


Solution

  • As ShamPooSham commented one way is to use a forkJoin operator. Take a look at the following snippet of code

    const teams$ = this.httpClient.get<Team[]>('/teams');
    const companies$ = this.httpClient.get<Company[]>('/companies');
    
    const teamsWithCompanies = forkJoin(teams$, companies$).pipe(
      switchMap((values: any[]) => {
        const teamsWithCompaniesResponse: TeamWithCompany[] = [];
        const teamArray = values[0];
        teamArray.forEach((team) => {
          const teamWithCompany: TeamWithCompany = {
              id: team.id,
              name: team.name,
              expertise: team.expertise,
              companyId: team.companyId,
              company: values[1].find(c => c.id === team.companyId)
          }
          teamsWithCompaniesResponse.push(teamWithCompany);
        })
    
        return of(teamsWithCompaniesResponse);
      })
    ).subscribe(response => {
      console.log('[RESPONSE]', response);
    })