【问题标题】: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?如何使用 RxJs 将两个数组组合成一个数组,其中第二个数组的每个元素将分配给每个对象属性的第一个数组?
【发布时间】:2020-07-26 19:10:25
【问题描述】:

我有两个接口,分别是Team和Company

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

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

这是示例数据:

"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
    }
]

所以我想根据 companyIdcompany 作为属性分配给每个团队。 像这样:

"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"
       }
    }
]

那么我如何使用 RxJs 来实现这一点。 我有两个 observable 分别返回 Team[] 和 Company[] 的 Observable。

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

那么,如何做到这一点?我知道它可以以命令式的方式完成(通过使用循环、if-else 等),但我想通过只使用反应式运算符、观察者来以反应式的方式做到这一点。

【问题讨论】:

  • 我认为“rxjs 方式”这样做没有意义,因为您将响应作为每个请求发出的数组,而不是作为流。我只需对两个 observable 做一个forkJoin,然后做所有必要的事情(或者我会以更实用的方式来做)

标签: arrays angular reactive-programming rxjs6 rxjs-observables


【解决方案1】:

得到两个数组响应后

let arr3 = this.teams.map((item, i) => Object.assign({}, item, { company: (this.companies.find((itmInner) => itmInner.id === this.teams[i].companyId)) }));
    console.log(arr3);

【讨论】:

    【解决方案2】:

    首先,您需要团队和公司对象来合并它们。所以你可以做的是

    this.httpClient.get<Team[]>('/teams').subscribe(teams => {
      this.httpClient.get<Company[]>('/companies').subscribe(companies => {
        //here you have teams and companies array
        var result = [];
    
        teams.forEach(team => {
          var company = companies.find(s => s.id == team.companyId);
          if(company){
          Object.assign(team , {company});
          result.push(team);
          }
        })
    
        console.log(result);
      })
    })
    

    这应该可以解决问题

    另外,如果你在不同的地方有这两个 observables,你会以某种方式找到一种方法来让这两个数组合并它。

    谢谢

    【讨论】:

    • 在订阅中进行订阅是不好的做法,并且性能会降低。使用您的代码,您需要先获得/teams,然后才能获得/companies,这可以并行完成。
    【解决方案3】:

    正如ShamPooSham 所评论的,一种方法是使用forkJoin 运算符。看看下面sn-p的代码

    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);
    })
    

    【讨论】:

    • 它有效,但我可以使用 zip 运算符吗?想知道。 ForkJoin 为我完成了这项工作。谢谢
    猜你喜欢
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    • 2022-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    相关资源
    最近更新 更多