Json 文档中的 Rxjs 映射数组到新的数组类型
Rxjs Map Array in Json Document to new Array type
我正在 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});
});
});
这行得通,但我知道有一种方法可以将其正确映射回服务代码。此外,以这种方式完成后,编译器会抱怨 "results.segments" 声明 "Property " 段“在类型 '{}' 上不存在。
如何在服务的 "getSegments" 方法中将检索到的数据映射到我需要的数组?
您可以扩展地图功能并将其从组件中删除,如下所示:
map(result => {
result = result.segments;
let data = [];
result.forEach(element => {
data.push({value: element.name, viewValue: element.name});
});
return data;
});
您可以通过 2 个步骤进行转换:
- pipe/map 提取段
- array/map转换为最终数据类型
请在此处查看示例: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;
});
您可以使用 RxJS 运算符 flatMap
,它是 mergeMap.
的别名
官方文档对flatMap
的描述如下:
Projects each element of an observable sequence to an observable
sequence and merges the resulting observable sequences or Promises or
array/iterable into one observable sequence.
我们可以使用 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
运算符 returns 一个可观察的段流,而不是段数组。
我正在 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});
});
});
这行得通,但我知道有一种方法可以将其正确映射回服务代码。此外,以这种方式完成后,编译器会抱怨 "results.segments" 声明 "Property " 段“在类型 '{}' 上不存在。
如何在服务的 "getSegments" 方法中将检索到的数据映射到我需要的数组?
您可以扩展地图功能并将其从组件中删除,如下所示:
map(result => {
result = result.segments;
let data = [];
result.forEach(element => {
data.push({value: element.name, viewValue: element.name});
});
return data;
});
您可以通过 2 个步骤进行转换:
- pipe/map 提取段
- array/map转换为最终数据类型
请在此处查看示例: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;
});
您可以使用 RxJS 运算符 flatMap
,它是 mergeMap.
官方文档对flatMap
的描述如下:
Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences or Promises or array/iterable into one observable sequence.
我们可以使用 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
运算符 returns 一个可观察的段流,而不是段数组。