RxSwift - Filtering Operators

The filtering operators operating on the next-events

Priya Talreja
Mac O’Clock
5 min readApr 26, 2020

--

Ignoring Operators

ignoreElements()

  • ignore .next event elements.
  • It will allow through stop events, i.e .completed and .errorevent.
  • The operator is useful when you do not care about the items being emitted by an Observable. You only want to get notified when an observable has terminated.
let ignoreElementExample = PublishSubject<String>()
let disposeBag = DisposeBag()
ignoreElementExample
.ignoreElements()
.subscribe { _ in
print("Yay! Work Completed!")
}.disposed(by: disposeBag)
ignoreElementExample.onNext("A")
ignoreElementExample.onNext("B")
ignoreElementExample.onNext("C")
ignoreElementExample.onCompleted()
Output:-
Yay! Work Completed!

elementAt()

  • It takes the index of the element you want to receive and ignores everything else.
  • The operator pulls an item located at a specified index location in the sequence of items emitted by the source Observable and emits that item as its own sole emission.
  • The operator is useful when you only want to handle the nth element emitted by an observable.
let elementAtExample = PublishSubject<String>()
let disposeBag = DisposeBag()
elementAtExample
.elementAt(1)
.subscribe(onNext: { (element) in
print("Element \(element)")
}, onError: { (err) in
print("\(err.localizedDescription)")
}, onCompleted: {
print("Completed!")
}) {
print("Disposed")
}.disposed(by: disposeBag)
elementAtExample.onNext("A")
elementAtExample.onNext("B")
elementAtExample.onNext("C")
elementAtExample.onCompleted()
Output:-
Element B
Completed!
Disposed

filter()

  • Emit only those items from an Observable that pass a predicate test.
  • It takes a predicate closure, which it applies to each element, allowing through only those elements for which the predicate resolves to true.
let filterExample = PublishSubject<Int>()
let disposeBag = DisposeBag()
filterExample
.filter { (integer) -> Bool in
integer < 5
}
.subscribe(onNext: { (element) in
print("Element \(element)")
}).disposed(by: disposeBag)
filterExample.onNext(2)
filterExample.onNext(8)
filterExample.onNext(3)
Output:-
Element 2
Element 3

Skipping Operators

skip()

  • We need to pass a number as a parameter to skip() operator. This number tells us how many elements to skip.
  • Suppress the first n items emitted by an Observable.
let skipExample = PublishSubject<String>()
let disposeBag = DisposeBag()
skipExample
.skip(2)
.subscribe(onNext: { (element) in
print("Element \(element)")
}).disposed(by: disposeBag)
skipExample.onNext("A")
skipExample.onNext("B")
skipExample.onNext("C")
Output:-
Element C

skipWhile()

  • Discards the elements until the specified condition becomes false.
  • skipWhile takes a predicate closure, as long as predicate evaluates to true, it will ignore the incoming elements.
  • Predicate returning true will cause the element to be skipped until it returns false. It is opposite of filter().

Unlike filter which will filter the elements for the life of the subscription, skipWhile will only skip until the condition evaluates to false, all the elements that come after will be allowed.

let skipWhileExample = PublishSubject<Int>()
let disposeBag = DisposeBag()
skipWhileExample
.skipWhile {
$0 % 2 == 0
}
.subscribe(onNext: { (element) in
print("Element \(element)")
}).disposed(by: disposeBag)
skipWhileExample.onNext(2)
skipWhileExample.onNext(4)
skipWhileExample.onNext(5)
skipWhileExample.onNext(7)
skipWhileExample.onNext(4)
Output:-
Element 5
Element 7
Element 4

skipUntil()

  • Filtering operators so far had some static conditions, skipUntil operator can be used for dynamically filter elements based on some other observable.
  • skipUnitl ignores elements emitted by the source observable until the trigger observable emits .next event.
let skipUntilExample = PublishSubject<Int>()let triggerObservable = PublishSubject<String>()
let disposeBag = DisposeBag()
skipUntilExample
.skipUntil(triggerObservable)
.subscribe(onNext: { (element) in
print("Element \(element)")
}).disposed(by: disposeBag)
skipUntilExample.onNext(1)
skipUntilExample.onNext(2)
triggerObservable.onNext("S")skipUntilExample.onNext(3)
skipUntilExample.onNext(4)
Output:-
Element 3
Element 4

Taking Operators

take()

  • Emit only the first n elements emitted by an Observable.
  • take() is opposite of skip().
let takeExample = PublishSubject<Int>()
let disposeBag = DisposeBag()
takeExample
.take(3)
.subscribe(onNext: { (element) in
print("Element \(element)")
}).disposed(by: disposeBag)
takeExample.onNext(2)
takeExample.onNext(4)
takeExample.onNext(6)
takeExample.onNext(8)
Output:-
Element 2
Element 4
Element 6

takeWhile()

  • takeWhile takes a predicate closure, as long as predicate evaluates to true, it will take the incoming elements.
  • In other words, it will take elements until the condition fails.
let takeWhileExample = PublishSubject<Int>()
let disposeBag = DisposeBag()
takeWhileExample
.takeWhile {
$0 % 2 == 0
}
.subscribe(onNext: { (element) in
print("Element \(element)")
}).disposed(by: disposeBag)
takeWhileExample.onNext(2)
takeWhileExample.onNext(4)
takeWhileExample.onNext(5)
takeWhileExample.onNext(7)
takeWhileExample.onNext(4)
Output:-
Element 2
Element 4

takeUntil()

  • Takes from the source observable until trigger observable emits an element.
  • Opposite of skipUnitil().
  • Discard any elements emitted by an Observable after a second i.e trigger Observable emits an item or terminates.
let takeUntilExample = PublishSubject<Int>()
let triggerObservable = PublishSubject<String>()
let disposeBag = DisposeBag()
takeUntilExample
.takeUntil(triggerObservable)
.subscribe(onNext: { (element) in
print("Element \(element)")
}).disposed(by: disposeBag)
takeUntilExample.onNext(1)
takeUntilExample.onNext(2)
triggerObservable.onNext("S")takeUntilExample.onNext(3)
takeUntilExample.onNext(4)
Output:-
Element 1
Element 2

Distinct Operators

distinctUntilChanged()

  • distinctUntilChanged only prevents duplicates that are right next to each other.
  • So in the below marble diagram, second event 2 gets through.
let distinctUntilChangedExample = PublishSubject<Int>()
let disposeBag = DisposeBag()
distinctUntilChangedExample
.distinctUntilChanged()
.subscribe(onNext: { (element) in
print("Element \(element)")
}).disposed(by: disposeBag)
distinctUntilChangedExample.onNext(1)
distinctUntilChangedExample.onNext(2)
distinctUntilChangedExample.onNext(4)
distinctUntilChangedExample.onNext(4)
distinctUntilChangedExample.onNext(2)
Output:-
Element 1
Element 2
Element 4
Element 2

Thank you. I hope this helps!

--

--