将多个可观察数组组合成新的对象数组
Combine multiple observable arrays into new object array
我有 3 个如下所示的可观察数组。
persons = [
{
"firstName":"john",
"lastName":"public",
"locationID":"1",
"departmentID":"100"
},
{
"firstName":"sam",
"lastName":"smith",
"locationID":"2",
"departmentID":"101"
}
]
departments = [{"departmentID": "100",
"name": "development"
},
{"departmentID": "101",
"name": "sales"
}]
locations = [{"locationID": "1", "name": "chicago"},
{"locationID":"2", "name": "ny"}]
我正在尝试将这 3 个组合成以下结果,
result = [
{
"firstName":"john",
"lastName":"public",
"location":"development",
"department":"sales"
},
{
"firstName":"sam",
"lastName":"smith",
"location":"ny",
"department":"sales"
}
]
为了得到想要的结果,我在 persons observable 上使用了 map 函数来提供新的对象数组。
this.store<Person>('persons')
.map(function(person){
let p = new personDetail()
p.firstName = person.firstName,
p.lastName = person.lastName
return p;
})
PersonDetail
对象具有 firstName
、lastName
、location
和 department
属性。如何查找可观察部门并获取 departmentID
的匹配行以获取部门名称?
我是 rxjs 库的新手,请告诉我是否有更好的方法来获得所需的结果。
不清楚你的 observables 到底发出了什么,所以我考虑了两个选择。
let persons = [
{
"firstName":"john",
"lastName":"public",
"locationID":"1",
"departmentID":"100"
},
{
"firstName":"sam",
"lastName":"smith",
"locationID":"2",
"departmentID":"101"
}
];
let departments = [
{"departmentID": "100", "name": "development"},
{"departmentID": "101", "name": "sales"}
];
let locations = [
{"locationID": "1", "name": "chicago"},
{"locationID": "2", "name": "ny"}
];
// Option 1: first observable emits persons one by one,
// locations and departments are emitted as whole arrays.
let o1: any = Observable.from(persons);
let o2: any = Observable.of(departments);
let o3: any = Observable.of(locations);
o1.withLatestFrom(o2, o3, (p, d, l) => {
// here it is probably better to convert array to some kind of map or dictionary,
// but I'm only showing Rxjs concept of doing such things.
let location = l.find(c => c.locationID === p.locationID);
let department = d.find(c => c.departmentID === p.departmentID);
return {
firstName: p.firstName,
lastName: p.lastName,
location: location ? location.name : "",
department: department ? department.name : ""
};
}).subscribe((f) => {
console.log(f);
});
// Option 2: all observables emit elements one by one.
// In this case we need to convert departments and locations to arrays.
o1 = Observable.from(persons);
o2 = Observable.from(departments);
o3 = Observable.from(locations);
o1.withLatestFrom(o2.toArray(), o3.toArray(), (p, d, l) => {
// this part of code is exactly the same as in previous case.
let location = l.find(c => c.locationID === p.locationID);
let department = d.find(c => c.departmentID === p.departmentID);
return {
firstName: p.firstName,
lastName: p.lastName,
location: location ? location.name : "",
department: department ? department.name : ""
};
}).subscribe((f) => {
console.log(f);
});
由于您很可能希望从远程服务获取部门和位置列表(发出另一个 HTTP 请求),因此我也会立即使用 Observables 来完成。
Observable.from(persons)
.mergeMap(person => {
let department$ = Observable.from(departments)
.filter(department => department.departmentID == person.departmentID);
let location$ = Observable.from(locations)
.filter(location => location.locationID == person.locationID);
return Observable.forkJoin(department$, location$, (department, location) => {
return {
'firstName': person.firstName,
'lastName': person.lastName,
'location': location.name,
'department': department.name,
};
});
})
.toArray()
.subscribe(result => console.log(result));
这会打印到控制台:
[ { firstName: 'john',
lastName: 'public',
location: 'chicago',
department: 'development' },
{ firstName: 'sam',
lastName: 'smith',
location: 'ny',
department: 'sales' } ]
有两个 Observables department$
和 location$
用 filter()
运算符过滤以获得唯一具有匹配 ID 的项目。然后 forkJoin()
运算符等待直到它们都完成。运算符 mergeMap()
然后重新发出从 forkJoin()
返回的值。最后 toArray()
我们将所有项目收集到一个数组中。
而不是 Observable.from(...)
,您可以获得您需要的任何服务(例如 http.get(...)
)。
观看现场演示:https://jsbin.com/nenekup/4/edit?js,console
类似问题: and
我认为 RxJS .zip 运算符可能是你的朋友。
据我了解,.zip 是这样发出的...
.zip(
Observable.from[array1].switchMap( // map to http response here ),
Observable.from[array2].switchMap( // map to http response here ),
Observable.from[array3].switchMap( // map to http response here )
).map((valueFromArray1, valueFromArray2, valueFromArray3) {
// Create your object here
})
类似的东西!希望能让您走上正轨。
.zip 应该在所有 3 个流都发出时第一次发出(并且当所有三个流都发出两次时它会发出第二次,等等) - 在你的场景中我希望所有三个流只发出一次,这使得这是 .zip
的简单案例
我有 3 个如下所示的可观察数组。
persons = [
{
"firstName":"john",
"lastName":"public",
"locationID":"1",
"departmentID":"100"
},
{
"firstName":"sam",
"lastName":"smith",
"locationID":"2",
"departmentID":"101"
}
]
departments = [{"departmentID": "100",
"name": "development"
},
{"departmentID": "101",
"name": "sales"
}]
locations = [{"locationID": "1", "name": "chicago"},
{"locationID":"2", "name": "ny"}]
我正在尝试将这 3 个组合成以下结果,
result = [
{
"firstName":"john",
"lastName":"public",
"location":"development",
"department":"sales"
},
{
"firstName":"sam",
"lastName":"smith",
"location":"ny",
"department":"sales"
}
]
为了得到想要的结果,我在 persons observable 上使用了 map 函数来提供新的对象数组。
this.store<Person>('persons')
.map(function(person){
let p = new personDetail()
p.firstName = person.firstName,
p.lastName = person.lastName
return p;
})
PersonDetail
对象具有 firstName
、lastName
、location
和 department
属性。如何查找可观察部门并获取 departmentID
的匹配行以获取部门名称?
我是 rxjs 库的新手,请告诉我是否有更好的方法来获得所需的结果。
不清楚你的 observables 到底发出了什么,所以我考虑了两个选择。
let persons = [
{
"firstName":"john",
"lastName":"public",
"locationID":"1",
"departmentID":"100"
},
{
"firstName":"sam",
"lastName":"smith",
"locationID":"2",
"departmentID":"101"
}
];
let departments = [
{"departmentID": "100", "name": "development"},
{"departmentID": "101", "name": "sales"}
];
let locations = [
{"locationID": "1", "name": "chicago"},
{"locationID": "2", "name": "ny"}
];
// Option 1: first observable emits persons one by one,
// locations and departments are emitted as whole arrays.
let o1: any = Observable.from(persons);
let o2: any = Observable.of(departments);
let o3: any = Observable.of(locations);
o1.withLatestFrom(o2, o3, (p, d, l) => {
// here it is probably better to convert array to some kind of map or dictionary,
// but I'm only showing Rxjs concept of doing such things.
let location = l.find(c => c.locationID === p.locationID);
let department = d.find(c => c.departmentID === p.departmentID);
return {
firstName: p.firstName,
lastName: p.lastName,
location: location ? location.name : "",
department: department ? department.name : ""
};
}).subscribe((f) => {
console.log(f);
});
// Option 2: all observables emit elements one by one.
// In this case we need to convert departments and locations to arrays.
o1 = Observable.from(persons);
o2 = Observable.from(departments);
o3 = Observable.from(locations);
o1.withLatestFrom(o2.toArray(), o3.toArray(), (p, d, l) => {
// this part of code is exactly the same as in previous case.
let location = l.find(c => c.locationID === p.locationID);
let department = d.find(c => c.departmentID === p.departmentID);
return {
firstName: p.firstName,
lastName: p.lastName,
location: location ? location.name : "",
department: department ? department.name : ""
};
}).subscribe((f) => {
console.log(f);
});
由于您很可能希望从远程服务获取部门和位置列表(发出另一个 HTTP 请求),因此我也会立即使用 Observables 来完成。
Observable.from(persons)
.mergeMap(person => {
let department$ = Observable.from(departments)
.filter(department => department.departmentID == person.departmentID);
let location$ = Observable.from(locations)
.filter(location => location.locationID == person.locationID);
return Observable.forkJoin(department$, location$, (department, location) => {
return {
'firstName': person.firstName,
'lastName': person.lastName,
'location': location.name,
'department': department.name,
};
});
})
.toArray()
.subscribe(result => console.log(result));
这会打印到控制台:
[ { firstName: 'john',
lastName: 'public',
location: 'chicago',
department: 'development' },
{ firstName: 'sam',
lastName: 'smith',
location: 'ny',
department: 'sales' } ]
有两个 Observables department$
和 location$
用 filter()
运算符过滤以获得唯一具有匹配 ID 的项目。然后 forkJoin()
运算符等待直到它们都完成。运算符 mergeMap()
然后重新发出从 forkJoin()
返回的值。最后 toArray()
我们将所有项目收集到一个数组中。
而不是 Observable.from(...)
,您可以获得您需要的任何服务(例如 http.get(...)
)。
观看现场演示:https://jsbin.com/nenekup/4/edit?js,console
类似问题:
我认为 RxJS .zip 运算符可能是你的朋友。
据我了解,.zip 是这样发出的...
.zip(
Observable.from[array1].switchMap( // map to http response here ),
Observable.from[array2].switchMap( // map to http response here ),
Observable.from[array3].switchMap( // map to http response here )
).map((valueFromArray1, valueFromArray2, valueFromArray3) {
// Create your object here
})
类似的东西!希望能让您走上正轨。
.zip 应该在所有 3 个流都发出时第一次发出(并且当所有三个流都发出两次时它会发出第二次,等等) - 在你的场景中我希望所有三个流只发出一次,这使得这是 .zip
的简单案例