Reputation: 403
Let's consider the following simplified situation:
I want to filter the apples observable such that the rotten apples don't pass the filter. More precisely, an apple A passes the filter if and only if the first item emitted by A.isRotten() is false. What is the best way to implement this filter?
After some thinking I could come up with this:
apples
.concatMap(apple =>
apple.isRotten()
.first()
.filter(bool => bool)
.map(bool => apple))
Which is written in javascript. ( ... => ... is a function). This works, but I think it is rather lengthy and difficult to understand. Is there a better way to do this kind of thing?
Upvotes: 8
Views: 4183
Reputation: 145890
One way to achieve that is like this, sorry I didn't get to adapt this to fruit filtering:
const orders$: Observable<Order[]> = searchOrders(...);
const filteredOrders$ = orders$.pipe(switchMap((orders) => {
// take all orders and determine visibility based on an observable
const visibilityRules = orders.map(o => {
return {
order: o,
visible$: o.isPaidFor$ // this is an observable on an Order object
};
});
const filtered = visibilityRules.map(o => o.visible$.pipe(map(visible => visible ? o.order : undefined )));
return (filtered.length == 0) ? of([]) : combineLatest(filtered).pipe(map(combined => combined.filter(x => x != undefined)));
}));
This filters 'paidFor' orders and emits a new array every time an order becomes paid or unpaid.
Note: If the isPaidFor$
observable can't change between searches then this whole exercise is pointless because there would be no reason to provide a 'live view' like this. This only makes sense if the observable can actually change between search results.
This could be extended to much more complicated rules if needed (such as adding filtering checkboxes) - that's why I created the intermediate visibilityRules
array - which strictly speaking is just for readability.
Upvotes: 0
Reputation: 84734
What you've got is fine and, tbh, I can't think of a more concise way of doing it. I'd probably use flatMap
rather than concatMap
if out-of-order apples aren't an issue.
If readibility is an issue for you, just move the implementation into it's one function (eg. filterObservable
that accepts a function that takes a value and returns an IObservable<bool>
)
Upvotes: 4
Reputation: 11581
You can do something like this:
var seq = Rx.Observable.from([1, 2, 3, 4, 5, 6])
.filter(x => {
let isRotten = true;
Rx.Observable.just(x % 2 === 0)
.first()
.subscribe(val => isRotten = val);
if (isRotten) {
return x;
}
});
seq.subscribe(x => console.log(x));
Upvotes: -3