스트림을 필터링하는 연산자들

SteadySlower·2022년 3월 31일
0

RxSwift

목록 보기
4/7
post-thumbnail

🔮  마블 다이어그램 출처: https://reactivex.io/documentation/operators.html 

Operator (연산자)

연산자는 Observable에서 발행한 데이터를 가공하는 역할을 합니다. 기본적으로 ReactiveX의 연산자들은 순수 함수 (Pure Function)이기 때문에 Thread-Safety를 충족합니다. (순수함수란 부작용을 일으키지 않는 함수를 의미합니다. 여기서 부작용은 원본 데이터의 수정한다는 의미입니다.)

Filtering Operators

Observable이 발행한 데이터들을 Filtering하는 Operator들입니다.

IgnoreElements()

발행되는 값들을 전부 무시하는 연산자입니다. 단 complete와 dispose 이벤트는 발생합니다.

import RxSwift

let subject = PublishSubject<String>()

let disposeBag = DisposeBag()

subject
    .ignoreElements() //👉 여기서 무시!
    .subscribe(onNext: { print($0) },
               onCompleted: { print("발행 끝") },
               onDisposed: { print("dispose 됨") })
    .disposed(by: disposeBag)

subject.onNext("발행 1")
subject.onNext("발행 2")
subject.onNext("발행 3")

subject.onCompleted() //👉 여기서는 출력!
//🖨 출력 결과
//🚫 발행된 내용은 모두 무시되고 
발행 끝
dispose 됨

Element(at:)

특정 인덱스의 발행물만 통과시키는 연산자입니다.

import RxSwift

let subject = PublishSubject<String>()
let disposeBag = DisposeBag()

subject
    .element(at: 1)
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

subject.onNext("발행 1") //👉 인덱스 0
subject.onNext("발행 2") //👉 인덱스 1
subject.onNext("발행 3") //👉 인덱스 2
//🖨 출력 결과
발행 2 //👉 인덱스 2만 출력됨!

filter

Array에서 사용하던 고차함수 filter와 유사한 연산자입니다. 해당 클로저가 true를 반환하는 값만 통과시킵니다.

import RxSwift

let subject = PublishSubject<Int>()
let disposeBag = DisposeBag()

subject
    .filter { $0 % 2 == 1 } //👉 여기서 true를 반환하는 값만 발행됨!
    .subscribe(onNext: { print("통과한 숫자: \($0)") })
    .disposed(by: disposeBag)

subject.onNext(1)
subject.onNext(2)
subject.onNext(3)
//🖨 출력 결과
통과한 숫자: 1
통과한 숫자: 3

skip

처음 n개의 발행물을 생략하고 그 이후의 발행물만 발행합니다.

import RxSwift

let subject = PublishSubject<String>()
let disposeBag = DisposeBag()

subject
    .skip(2)
    .subscribe(onNext: { print("최신 뉴스: \($0)") })
    .disposed(by: disposeBag)

subject.onNext("그제 뉴스")
subject.onNext("어제 뉴스")
subject.onNext("오늘 뉴스")
subject.onNext("내일 뉴스")
subject.onNext("모레 뉴스")
//🖨 출력 결과
최신 뉴스: 오늘 뉴스
최신 뉴스: 내일 뉴스
최신 뉴스: 모레 뉴스

skip(while:)

조건이 true인 동안은 skip합니다. 하지만 일단 true가 되면 그 이후 부터는 무조건 발행합니다!

import RxSwift

let subject = PublishSubject<Int>()
let disposeBag = DisposeBag()

subject
    .skip(while: { $0 < 0 }) //👉 음수가 발행되는 동안은 skip
    .subscribe(onNext: { print("통과한 숫자: \($0)") })
    .disposed(by: disposeBag)

subject.onNext(-2)
subject.onNext(-1)
subject.onNext(1) //👉 skip 조건이 깨짐! = 무조건 출력
subject.onNext(2)
subject.onNext(-100) //👉 skip 조건이 깨졌기 때문에 음수여도 출력
subject.onNext(-200)
//🖨 출력 결과
통과한 숫자: 1
통과한 숫자: 2
통과한 숫자: -100
통과한 숫자: -200

skip(until:)

인자로 다른 Observable을 받습니다. 해당 Observable이 발행되기 전에 발행된 데이터는 skip합니다.

import RxSwift

let subject = PublishSubject<String>()
let anotherSubject = PublishSubject<String>()
let disposeBag = DisposeBag()

subject
    .skip(until: anotherSubject)
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

anotherSubject
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

subject.onNext("원래 발행 1")
subject.onNext("원래 발행 2") //👉 1, 2는 skip
anotherSubject.onNext("다른 발행 1")
subject.onNext("원래 발행 3") //👉 anotherSubject가 발행되어서 이제부터 출력됨!
//🖨 출력 결과
다른 발행 1
원래 발행 3

take

stream에서 얻을 데이터의 갯수를 정합니다. n개 이외의 발행은 무시합니다. skip의 반대라고 생각하면 됩니다.

import RxSwift

let subject = PublishSubject<String>()
let disposeBag = DisposeBag()

subject
    .take(2)
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

subject.onNext("발행 1")
subject.onNext("발행 2")
subject.onNext("발행 3") //👉 2개 이후는 무시!
subject.onNext("발행 4")
subject.onNext("발행 5")
//🖨 출력 결과
발행 1
발행 2

take(while:)

조건이 만족하는 동안만 발행합니다. 일단 조건을 만족하지 않는 데이터가 들어오면 그 이후는 무조건 발행하지 않습니다. skip(while:)의 반대라고 생각하면 됩니다.

import RxSwift

let subject = PublishSubject<Int>()
let disposeBag = DisposeBag()

subject
    .take(while: { $0 > 0 }) //👉 양수가 발행되는 동안만 take
    .subscribe(onNext: { print("통과한 숫자: \($0)") })
    .disposed(by: disposeBag)

subject.onNext(1)
subject.onNext(2)
subject.onNext(-1) //👉 take 조건이 깨짐! = 무조건 무시!
subject.onNext(100) //👉 take 조건이 깨졌기 때문에 양수여도 무시!
subject.onNext(200) 
subject.onNext(300)
//🖨 출력 결과
통과한 숫자: 1
통과한 숫자: 2

take(until:)

다른 Observable이 발행할 때까지만 발행합니다. 마찬가지로 skip(until:)의 반대라고 생각하면 됩니다.

import RxSwift

let subject = PublishSubject<String>()
let anotherSubject = PublishSubject<String>()
let disposeBag = DisposeBag()

subject
    .take(until: anotherSubject)
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

anotherSubject
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

subject.onNext("원래 발행 1")
subject.onNext("원래 발행 2") //👉 1, 2는 take!
anotherSubject.onNext("다른 발행 1")
subject.onNext("원래 발행 3") //👉 anotherSubject가 발행되어서 이제부터 무시됨!
//🖨 출력 결과
원래 발행 1
원래 발행 2
다른 발행 1
profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.

0개의 댓글