2016-07-27 82 views
0

我必须遍历数组,找到其他数组中的对应对象并将结果合并到对象中。如何迭代多个数组而不嵌套观察值

假设我有三个阵列

var users = [ 
    { name: "A", type: 2, level: 1 }, 
    { name: "B", type: 1, level: 2 } 
] 
var types = [ 
    { description: "Type 1", id: 1 }, 
    { description: "Type 2", id: 2 } 
] 
var levels = [ 
    { description: "Level 1", id: 1 }, 
    { description: "Level 2", id: 1 } 
] 

我想有以下结果:

var users = [ 
    { name: "A", type: 2, level: 1, levelDescription: "Level 1", typeDescription: "Type 2" }, 
    { name: "B", type: 1, level: 2, levelDescription: "Level 2", typeDescription: "Type 1" } 
] 

我知道我能做到这样说,这

var usersObservable = RX.Observable.fromArray(users); 
var typesObservable = Rx.Observable.fromArray(types); 
var levelsOBservable = Rx.Observable.fromArray(levels); 

var uiUsers= [];// not really needed because I will use the same users array again. 

usersObservable.map(function(user) { 
     typesObservable.filter(function(type) { 
     return type.id == user.type; 
    }).subscribeOnNext(function(userType) { 
     user.typeDescription = userType.description; 
    }); 
    return user; 
}).map(function(user) { 
     levelsOBservable.filter(function(level) { 
     return level.id == user.levelId; 
    }).subscribeOnNext(function(level) { 
     user.levelDescription = level.description; 
    }); 
    return user; 
}) 
.subscribeOnNext(function(user) { 
    uiUsers.push(user); 
}) 

我想有没有嵌套Observables的解决方案。
谢谢。

回答

0

我不确定你为什么在这个问题上使用Rx。你有空间数据(即数组),而不是数据随着时间的推移(即可观察的序列)。但是你将这些数组强制为Rx来创建一个非常复杂的解决方案。

我认为你正在寻找类似于这里的答案https://stackoverflow.com/a/17500836/393615的地方,你会加入源数组类型。在你的情况下,你只需“内部连接”两次以结合所有三个数据集。

0

您可以使用switchMap运算符将运算符归档,该运算符将过滤流的结果与原始流的最新值组合,并使用投影函数将结果合并到单个对象中。这可以在您的示例中进行概括,以便您可以在两种情况下使用通用的高阶函数。见fiddle

完整代码(ES2015,RxJS5):

const users = [ 
    { name: "A", type: 2, level: 1 }, 
    { name: "B", type: 1, level: 2 } 
]; 
const types = [ 
    { description: "Type 1", id: 1 }, 
    { description: "Type 2", id: 2 } 
]; 
const levels = [ 
    { description: "Level 1", id: 1 }, 
    { description: "Level 2", id: 2 } 
]; 

const users$ = Rx.Observable.from(users); 
const types$ = Rx.Observable.from(types); 
const levels$ = Rx.Observable.from(levels); 

function join(s$, sourceProperty, targetProperty, streamProperty) { 
    return function(initObj) { 
    const stream$ = s$.filter(x => x.id === initObj[sourceProperty]); 
    return Rx.Observable.combineLatest(
     Rx.Observable.of(initObj), 
     stream$, 
     (obj, streamObj) => { 
     const prop = streamObj[streamProperty]; 
     return Object.assign({}, obj, { [targetProperty]: prop }); 
     } 
    ); 
    }; 
} 

users$ 
    .switchMap(join(types$, 'type', 'typeDescription', 'description')) 
    .switchMap(join(levels$, 'level', 'levelDescription', 'description')) 
    .subscribe(x => console.log(x));