2016-07-27 35 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));