我有以下类和数组
class Hero {
id: number;
name: string;
}
const HEROES: Hero[] = [
{ id: 11, name: 'Narco' },
{ id: 12, name: 'Narco' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Bombasto' },
{ id: 15, name: 'Bombasto' },
{ id: 16, name: 'Dynama' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dynama' },
{ id: 19, name: 'Dynama' },
{ id: 20, name: 'Dynama' }
];
我想创建一个将HEROES
数组视为源的observable,将数组按name
分组并将结果作为单个数组发出,即我应该最终得到三个数组,一个用于Narco
,一个用于Bombasto
,一个用于Dynama
。
我可以按如下方式创建我的源可观察
var heroSource = Observable.create((observer:any) => {
HEROES.forEach((hero: Hero) => {
observer.next(hero);
})
});
然后我可以使用groupBy
分组英雄,即
var groupHeroSource = heroSource
.groupBy((hero: Hero) => {return hero.name});
这有效地为我提供了尽可能多的可观察量,因为我的HEROES
数组中有不同的名称(本例中为3个)。但是,这些将作为一个序列发出,理想情况下我希望buffer
直到heroSource
完成。如何在我的分组可观察对象的rxjs中使用buffer
运算符,以便发出单个集合?
答案 0 :(得分:3)
首先,您可以更简单地创建初始可观察量:
var heroSource = Observable.from(HEROES);
接下来,您的groupBy映射器/选择器可以缩写为:
var groupHeroSource = heroSource.groupBy((hero: Hero): string => hero.name);
为了解决原始问题,我需要缓冲流,因为它们准备好了一个时间为0的缓冲区就能完成工作(我想应该有一个更优雅的解决方案),使用take(1)来只有第一个结果(并避免重复缓冲)然后合并所有:
var finalGroup = groupHeroSource.map((ob) => ob.bufferWithTime(0).take(1)).mergeAll();
请注意,由于您的数组实际上是静态的,将它放在流中然后映射它可能不是最简单的解决方案,您可以简单地减少它:
var grouped = HEROES.reduce((acc: any, hero: Hero) => {
acc[hero.name] = acc[hero.name] || [];
acc[hero.name].push(hero);
return acc;
}, {});
由于Object.values不是标准的,你必须迭代键才能得到一个数组,但它可能更适合你的需要