如何在没有嵌套observable的情况下迭代多个数组

时间:2016-07-27 17:39:59

标签: system.reactive rxjs rxjs5

我必须遍历数组,在其他数组中找到对应的对象,将结果合并到对象中。

假设我有三个数组

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的解决方案 感谢。

2 个答案:

答案 0 :(得分:1)

我不确定你为什么要使用Rx解决这个问题。您有空间数据(即数组),而不是随时间变化的数据(即可观察序列)。但是你强迫这些数组进入Rx然后创建一个非常复杂的解决方案。

我认为您正在寻找类似于https://stackoverflow.com/a/17500836/393615的答案,您将加入源数组类型。在你的情况下,你只是"内部加入"两次合并所有三个数据集。

答案 1 :(得分: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));