After using RxSwift for a few months, I can safely say that filtering is a key feature that saves me a lot of code. Knowing when to use which filter operators requires a basic overview, so let’s look at 7 of my favorite filter operators provided by this library.
RxSwift is a Swift implementation of the popular ReactiveX library. This library can help you very well when it comes to filtering data. It has various operators that allow you to filter the data in various ways so that you only deliver the data you want your subscribers to receive.
Essentially, these operators are conditional constraints on the next event. This means that all next event elements emitted by the observable will pass through the operator you specify. Each element needs to satisfy the operator’s requirements – if not, they will be discarded.
Most operators operate on observable sequences and return an observable sequence. This way, we are able to chain these operators because the next operator takes the output of the previous operator as input.
One thing to note is that you cannot use these operators to filter stop-events, i.e. completed-events and error-events. The filter operator only operates on next events.
1. filter()
The first operator in the list is filter
the operator.
The way this operator works is that the filter operator takes a predicate as an argument. A predicate serves as a conditional constraint that must be satisfied by every element emitted by the observable. This way, the predicate will be applied to all elements and determine whether each element is allowed through the subscriber.
Take a look at this marble diagram:
In this case, filter()
only elements with values greater than 10 will be allowed to pass. These elements will reach the next operator and the remaining elements will be removed.
Now, let’s look at a code example:
import RxSwift
let bestSellingAlbums = [
(title: "Thriller", salesInMillions: 93),
(title: "Eagles: Their Greatest Hits 1971-1975", salesInMillions: 41),
(title: "Hotel California", salesInMillions: 32),
(title: "Come on Over", salesInMillions: 29),
(title: "Led Zeppelin IV", salesInMillions: 29),
(title: "The Bodyguard Soundtrack", salesInMillions: 28),
(title: "Rumours", salesInMillions: 27),
(title: "Back in Black", salesInMillions: 26),
(title: "21", salesInMillions: 25),
(title: "Jagged Little Pill Year: 1995", salesInMillions: 24),
]
let disposeBag = DisposeBag()
//
Observable.from(bestSellingAlbums)
.filter { album in
album.salesInMillions >= 30
}
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// Output:
// (title: "Thriller", salesInMillions: 93)
// (title: "Eagles: Their Greatest Hits 1971-1975", salesInMillions: 41)
// (title: "Hotel California", salesInMillions: 32)
2. skip() & skipWhile()
As the names suggest, the purpose of these two operators is to skip data at some point.
Using skip
the operator, you pass numbers to it as arguments. This number tells us how many elements to ignore. All subsequent elements are allowed to be passed to subscribers. Therefore, skip(2)
the first two elements are ignored and all subsequent elements are passed through.
Using skipWhile
the operator, you can pass a predicate that true
will ignore the passed elements as long as it evaluates to . When its value false
is , all subsequent elements will be allowed to pass.
Let’s see it in code:
import RxSwift
let bestSellingAlbums = [
(title: "Thriller", salesInMillions: 93),
(title: "Eagles: Their Greatest Hits 1971-1975", salesInMillions: 41),
(title: "Hotel California", salesInMillions: 32),
(title: "Come on Over", salesInMillions: 29),
(title: "Led Zeppelin IV", salesInMillions: 29),
(title: "The Bodyguard Soundtrack", salesInMillions: 28),
(title: "Rumours", salesInMillions: 27),
(title: "Back in Black", salesInMillions: 26),
(title: "21", salesInMillions: 25),
(title: "Jagged Little Pill Year: 1995", salesInMillions: 24),
]
let disposeBag = DisposeBag()
//
Observable.from(bestSellingAlbums)
.skipWhile { album in
album.salesInMillions > 30
}
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// Output:
// (title: "Come on Over", salesInMillions: 29)
// (title: "Led Zeppelin IV", salesInMillions: 29)
// (title: "The Bodyguard Soundtrack", salesInMillions: 28)
// (title: "Rumours", salesInMillions: 27)
// (title: "Back in Black", salesInMillions: 26)
// (title: "21", salesInMillions: 25)
// (title: "Jagged Little Pill Year: 1995", salesInMillions: 24)
3. take() & takeWhile()
Next, we have the various get operators. These are the opposite of skip operators. The skip operator will exclude certain data based on a condition, but the get operator will include the data as you specify.
take
operator is skip
the opposite of operator. It works as you expect. Using take
the operator, you can specify a certain number of elements that are allowed to pass. All elements after this number will be ignored.
You guessed it, takeWhile
operator is skipWhile
the opposite of operator. Using takeWhile
the operator, you can pass a predicate that true
allows incoming elements as long as it evaluates to . When it evaluates to false
, all subsequent elements are ignored.
4. elementAt()
This is a nifty little operator you can’t ignore. elementAt
The operator will filter out all subsequent events except the element you specify at an index.
In code it would look like this:
import RxSwift
let bestSellingAlbums = [
(title: "Thriller", salesInMillions: 93),
(title: "Eagles: Their Greatest Hits 1971-1975", salesInMillions: 41),
(title: "Hotel California", salesInMillions: 32),
(title: "Come on Over", salesInMillions: 29),
(title: "Led Zeppelin IV", salesInMillions: 29),
(title: "The Bodyguard Soundtrack", salesInMillions: 28),
(title: "Rumours", salesInMillions: 27),
(title: "Back in Black", salesInMillions: 26),
(title: "21", salesInMillions: 25),
(title: "Jagged Little Pill Year: 1995", salesInMillions: 24),
]
let disposeBag = DisposeBag()
Observable.from(bestSellingAlbums)
.elementAt(5) //
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// Output:
// (title: "The Bodyguard Soundtrack", salesInMillions: 28),
5. ignoreElements()
Last but not least, we have ignoreElements
the operator.
As you can see from this pinball diagram, ignoreElements()
all next event elements will simply be ignored. This way, you can ignore the next event and only subscribe to the stop event and perform actions accordingly.
Summarize
We looked at the most common filter operators provided by RxSwift. You can find the full list of available operators [here] (Thanks for reading. Leave the cover to let me know what other RxSwift related topics you’d like me to cover.)
thanks for reading. Leave a comment and let me know what other RxSwift related topics you’d like me to cover.