web-dev-qa-db-ja.com

RxjsはJsonドキュメントの配列を新しい配列タイプにマップします

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

そして、コンポーネントの配列を次のように変換します。

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

これは機能しますが、これをサービスコードに適切にマッピングする方法があることを私は知っています。また、この方法で実行すると、コンパイラは「結果」について文句を言います。segments "プロパティ" segments "はタイプ '{}'に存在しません。

取得したデータを、サービスの「getSegments」メソッドで必要な配列にマッピングするにはどうすればよいですか?

3
Eric

変換は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;
});
6
hamilton.lima

次のように、map関数を拡張して、コンポーネントから削除できます。

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

mergeMap のエイリアスであるRxJS演算子flatMapを使用できます。

公式ドキュメントでは、flatMapについて次のように説明しています。

監視可能なシーケンスの各要素を監視可能なシーケンスに投影し、結果の監視可能なシーケンスまたはPromiseまたはarray/iterableを1つの監視可能なシーケンスにマージします。

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

これがどのように機能するかの詳細な説明:

この 記事 は、flatMapがどのように機能し、RxJSオブザーバブルではなく配列で機能するバージョンのflatMapを実装するかを次のようにうまく説明しています。

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演算子は、セグメントの配列ではなく、監視可能なセグメントのストリームを返します。

0
matthew