I have a mock file containing a collection of Tasks, each of which has a due date. Currently (below) I have the creation of a simple observable that, when subscribed to, returns the collection of mocked Tasks. What I'm failing to figure out is how I can process the flat array of Tasks to group them by their due date, returning a structure like;
// Current data structure (unstructured)
[{due: "2016-01-01"}, {due: "2016-01-01"}, {due: "2016-01-02"}, ...]
// Desired structure for consumption
{
"2016-01-01": [{...}, {...}],
"2016-01-02": [{...}, {...}, {...}],
"2016-01-03": [{...}]
}
My current observable creation code is as follows;
// Service...
tasks: Observable<Task[]>;
// init() called from the constructor
private init() {
this.tasks = Observable.create(observer => {
observer.next(mockTasks);
});
}
getTasks() {
return this.tasks;
}
Which is consumed in my component as follows;
// Component...
ngOnInit() {
this.taskService.getTasks().subscribe(tasks => {
this.tasks = tasks; // Contains the collection of tasks as expected
});
}
This works fine - I get my full array of tasks back as expected. I've tried using the groupBy
operator to achieve the above but the observable created via Observable.create()
does not appear to have that method available. I've been referring to this resource to attempt to achieve this and I notice that Observable.from()
is used instead of .create()
, however this also does not appear to be an available function in my service.
groupBy
) the way to go with formatting the data as above (and how can this be achieved)? Or should this be manually formatted?Thanks!
You're mixing several things, I guess. Observables always have the factor time in it, so you're emitting things over time through the help of an observable. If you only want to group things in a static array, observables are the wrong approach.
In your case you have several dats
const tasks =
[ {due: "2016-01-01"}
, {due: "2016-01-01"}
, {due: "2016-01-02"}
];
If you're about to put them in an Observable, that's possible but it would just output the array once and that's it.
const observable = Rx.Observable.of(tasks);
observable.subscribe(x => console.log('All at once', x));
// output: All at once [ {due: "2016-01-01"}, {due: "2016-01-01"}, {due: "2016-01-02"} ];
If you want to distribute them in time - and now we're getting closer to what Observables are for - you can do this also
const observable2 = Rx.Observable.from(tasks);
observable2.subscribe(x => console.log('One after the other', x));
// output: 'One after the other' {due: "2016-01-01"}
// 'One after the other' {due: "2016-01-01"}
// 'One after the other' {due: "2016-01-02"}
Now let's assume we have a data source that once in a while provides a new task and we want to group them over time. This is what it would look like:
const observable3 = Rx.Observable.from(tasks);
observable3
.scan((acc, obj) => {
let oldValue = acc[obj.due] || 0;
acc[obj.due] = ++oldValue;
return acc;
}, {})
.subscribe(x => console.log(x));
// output: { 2016-01-01: 1 }
// { 2016-01-01: 2 }
// { 2016-01-01: 2, 2016-01-02: 1 }
So depending on your needs Observables might be the right thing. If data is distributed in time it's perfectly possible to group them as shown above. I've uploaded the code to jsbin to play around with it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With