使用RxJs映射将一种类型的数组转换为另一种类型的数组

时间:2019-07-26 07:03:56

标签: angular rxjs

在我的 Angular 应用程序中,我使用 HttpClient 从服务器获取 json 数据。但是,我需要在客户端对返回的数据进行一些转换。

因此,我尝试将服务器返回的 Type A 数组转换为带有以下代码段的 Type B 数组。

this.http.get<any[]>(this.env.accounts.url.accountTypes).pipe(map(e => {
    console.log(e); // print the retuned array not a single item
    return {'label': e.name, 'value': e.id}
  }
)).subscribe(data => {
  this.accountTypes = data;
  console.log(this.accountTypes); // prints {label: undefined, value: undefined}
});

我一定做错了,但是我无法弄清楚这里出了什么问题。

服务器返回的数组如下:

[
  {name: "Name 1", id: 1},
  {name: "Name 2", id: 2},
  {name: "Name 3", id: 3},
]

我需要将其转换为以下格式

[
  {label: "Name 1", value: 1},
  {label: "Name 2", value: 2},
  {label: "Name 3", value: 3},
]

有人可以指出我的代码出了什么问题以及如何解决它。

4 个答案:

答案 0 :(得分:3)

如评论中所述,请同时映射数组内容

return e.map(entry => {'label': entry.name, 'value': entry.id});

答案 1 :(得分:1)

您可以使用地图运算符转换数据:

var result = [];
x.map(e => {
  const obj = {};
  obj['label'] = e.name;
  obj['value'] = e.id;
  result.push(obj);
})

答案 2 :(得分:1)

您将Array.map与RxJS的map运算符混淆。

如RxJS文档中针对地图操作符所述,Map的目的是

  

对来自源的每个值应用投影。

您可以做的是这样:

this.http.get<any[]>(this.env.accounts.url.accountTypes)
  .pipe(
    map(res => {
      // insert logic 
      const data = res.map(obj => ({
        label: obj.name,
        value: obj.id
      }));
      return data;
    })
  )).subscribe(data => {
    this.accountTypes = data;
    console.log(this.accountTypes); // prints {label: undefined, value: undefined}
  });

答案 3 :(得分:0)

当然有很多解决方案,但是模型适配器可以是通用解决方案。

// app/core/adapter.ts
export interface Adapter<T> {
    adapt(item: any): T;
}
export class AccountType {
//.....
}
export class AccountAdapter implements Adapter<AccountType> {

    adapt(item: any): AccountType {
        return new AccountType(
            item.id,
          --  item.name,
          ++  item.value,
        );
    }
}


export class AccountService {
    private baseUrl = 'http://api.*';
    constructor(
        private http: HttpClient,
        private adapter: AccountAdapter,
    ) { }

    list(): Observable<AccountType[]> {
        const url = `${this.baseUrl}/`;
        return this.http.get(url).pipe(
            // Adapt each item in the raw data array
            map((data: any[]) => data.map(item => this.adapter.adapt(item))),
        );
    }
}

this example may help more