Higher-Order Observable
If you want a higher-order observable, you can actually use the groupBy
rxjs operator.
const data = [
{groupId: "foo", value: 1},
{groupId: "foo", value: 3},
{groupId: "foo", value: 5},
{groupId: "bar", value: 42},
{groupId: "bar", value: 1337},
];
from(data).pipe(
groupBy(item => item.groupId)
)
.subscribe(console.log);
This will result in an observable which emits one observable per group, and on each of those inner observables, the corresponding items will be emitted.
Observable of Groups
If instead you want an observable which simply emits the groups, then this has actually nothing to do with rxjs or its groupBy
operator. Instead, it's merely a basic question about how to group an array in Javascript.
There is no built-in method for this, but libraries like lodash come with such functions. You can also do it by hand:
const data = [
{groupId: "foo", value: 1},
{groupId: "foo", value: 3},
{groupId: "foo", value: 5},
{groupId: "bar", value: 42},
{groupId: "bar", value: 1337},
];
const groupBy = (data, keyFn) => data.reduce((agg, item) => {
const group = keyFn(item);
agg[group] = [...(agg[group] || []), item];
return agg;
}, {});
of(data).pipe(
map(data => groupBy(data, item => item.groupId))
)
.subscribe(console.log);
This will emit once for the entire data set, but will emit
{
"foo":[
{"groupId":"foo","value":1},
{"groupId":"foo","value":3},
{"groupId":"foo","value":5}
],
"bar":[
{"groupId":"bar","value":42},
{"groupId":"bar","value":1337}
]
}