Rxjs将Json Document中的数组映射为新的数组类型

时间:2018-08-30 13:29:09

标签: javascript mapping angular6 rxjs6

我正在Angular Service中从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)
  );
}

然后我像这样在Component中变换数组:

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

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

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

3 个答案:

答案 0 :(得分: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 observables,如下所示:

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运算符返回可观察的段流,而不是段数组。

答案 1 :(得分:1)

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

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

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

ExecuteSqlCommand()

答案 2 :(得分:0)

您可以扩展map函数并将其从组件中删除,如下所示:

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