【问题标题】:Rxjs Map Array in Json Document to new Array typeRxjs 将 Json 文档中的数组映射到新的数组类型
【发布时间】:2018-08-30 13:29:09
【问题描述】:

我正在 Angular 服务中从 PouchDB 检索文档。文档按以下格式检索:

{
"_id":"segments",
"_rev":"1-4f0ed65cde23fe724db13bea1ae3bb13",
"segments":[
    { "name":"Aerospace" },
    { "name":"Auto repair" },
    { "name":"Commercial" },
    { "name":"Education" },
    { "name":"Energy" },
    { "name":"Farm/ranch" },
    { "name":"Furniture" },
    { "name":"Heavy Equipment" },
    { "name":"Hobbyist" },
    { "name":"Infrastructure" },
    { "name":"Luxury/Leisure" },
    { "name":"Military" },
    { "name":"MUP" },
    { "name":"Processing" },
    { "name":"Rail" },
    { "name":"Transportation" }
]}

我想将它映射到一个新的数组,如下所示:

[
  { value: "Aerospace", viewValue: "Aerospace" },
  { value: "Auto Repair", viewValue: "Auto Repair" },
  { value: "Commercial", viewValue: "Commercial" }
  ...
 ]

为此,我在我的服务中尝试了以下代码:

getSegments(): Observable<any[]> {
  return from(this.database.get('segments'))
  .pipe(
    map((results) => results.segments)
  );
}

然后我像这样在组件中转换数组:

segments: SegmentsLookup[] = [];
...
this.lookupDbService.getSegments()
  .subscribe(data => {
    data.forEach(element => {
      this.segments.push({value: element.name, viewValue: element.name});
  });
});

这可行,但我知道有一种方法可以将其正确映射回服务代码。此外,以这种方式完成时,编译器会抱怨“结果。”指出“类型'{}'上不存在属性“段”。

如何在服务的“getSegments”方法中将检索到的数据映射到我需要的数组?

【问题讨论】:

    标签: javascript mapping angular6 rxjs6


    【解决方案1】:

    你可以做的转换是2个步骤:

    • 管道/地图提取段
    • 要转换为最终数据类型的数组/映射

    请在此处查看示例:https://stackblitz.com/edit/angular-ikb2eg?file=src%2Fapp%2Fapp.component.ts

    let transformedData = observableData.pipe(
      map(data => {
        console.log(data, data.segments.length);
        return data.segments.map(element => {
          return { value: element["name"], viewValue: element["name"] };
        });
      })
    );
    
    transformedData.subscribe(data => {
      this.mylist = data;
    });
    

    【讨论】:

      【解决方案2】:

      你可以使用RxJS操作符flatMap,它是mergeMap的别名。

      官方文档对flatMap的描述如下:

      将可观察序列的每个元素投影到可观察序列 序列并合并生成的可观察序列或 Promises 或 数组/可迭代成一个可观察序列。

      我们可以像这样使用flatMap,然后是RxJS操作符map

      • flatMap 提取片段
      • map 转换为最终数据类型
      const transformedData = observableData.pipe(
        flatMap(data => data.segments),
        map(segment => ({
          value: segment['name'],
          viewValue: segment['name'],
        })),
      )
      
      transformedData.subscribe(data => {
        this.mylist = data;
      });
      

      详细解释其工作原理:

      这个article 很好地解释了flatMap 的工作原理并实现了flatMap 的一个版本,它适用于数组而不是RxJS 可观察对象,如下所示:

      function flatMap (arr, fn) {
        return arr.reduce((flatArr, subArray) => flatArr.concat(fn(subArray)), [])
      }
      

      如果我们将它与您的数据库查询结果一起使用,我们会看到我们提取了段。

      const data = {
      "_id": "segments",
      "_rev": "1-4f0ed65cde23fe724db13bea1ae3bb13",
      "segments": [
        { "name": "Aerospace" },
        { "name": "Auto repair" },
        // ...
      ]};
      
      const segments = flatMap([data], x => x.segments);
      
      console.log(segments);
      
      // > [
      // >  { "name": "Aerospace" },
      // >  { "name": "Auto repair" },
      // >  ...
      // > ]
      

      RxJS flatMap 运算符返回可观察的段流,而不是段数组。

      【讨论】:

      • 您需要combineAll() 将其转换回数组吗?
      【解决方案3】:

      您可以扩展地图功能并将其从组件中删除,如下所示:

      map(result => {
              result = result.segments;
              let data = [];
              result.forEach(element => {
                  data.push({value: element.name, viewValue: element.name});
              });
              return data;
       });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-17
        • 2018-07-12
        • 1970-01-01
        • 1970-01-01
        • 2020-01-18
        • 2016-10-17
        • 2023-04-04
        • 1970-01-01
        相关资源
        最近更新 更多