[RxSwift] Filtering Operators

나는 사과·2021년 4월 29일
0

RxSwift

목록 보기
6/8

filter는 들어오는 데이터 중에서 필요한 데이터는 취하고 필요하지 않는 데이터는 제외시키는 것으로 많이 알고 있다. 이번에는 RxSwift에서 이런 필터링하는 연산에 대해서 정리해보려고 한다.

Ignoring Operators

  1. .ignoreElements()

    그림을 보면 (1,2,3) 이벤트가 방출이 되는데 ignoreElements()를 적용하게 되면 구독자에게 이벤트가 넘어가지 않는다. 하지만 점선으로 종료되는 시점은 구독자에게 넘어가는 것을 볼 수 있다.
let observer = Observable.of(1,2,3)
let disposeBag = DisposeBag()

observer.ignoreElements()
    .subscribe({ (value) in
        print(value)
        
    })
    .disposed(by: disposeBag)

// completed

위 코드에서도 마찬가지로 (1,2,3) 요소를 출력하려고 했지만 아무것도 출력이 되지 않았다.
즉, 모든 .next이벤트는 무시하고 .completed.error 이벤트만 허용한다

  1. .elementAt
    Observer에서 방출된 n번째 요소만 처리하려는 경우 사용할 수 있다. 사용방법은 코드에서 보려고 한다.
let observer = Observable.of(1,2,3)
let disposeBag = DisposeBag()

observer.elementAt(0)
    .subscribe({ (value) in
        print(value)

    })
    .disposed(by: disposeBag)
    
// next(1)
// completed

위 코드에서 (1,2,3) 요소들을 출력하려고 하는데 .elementAt(index)를 사용해서 해당 index에 해당하는 값을 구독자에게 방출한다. 그래서 위 코드에서는 0번째 인덱스에 해당하는 값인 1이 넘어왔다.

  1. filter
    다른 언어에서 사용했던 filter처럼 같은 방식으로 사용할 수 있다. 수식을 넣고 그 수식에 해당하는 요소만 구독자에게 넘겨지는 방식이다.
    let observer = Observable.of(1,2,3,4,5,6,7,8,9,10)
    let disposeBag = DisposeBag()

observer.filter({ (value) -> Bool in
value % 2 == 0
})
.subscribe({ (value) in
print(value)
})
.disposed(by: disposeBag)

// next(2)
// next(4)
// next(6)
// next(8)
// next(10)
// completed

위 코드를 보면 1~10까지의 요소 중 `.filter`를 통해서 나머지가 0인 요소만 구독자에게 넘기는 방식을 사용해서 짝수 요소만 출력이 된 모습을 볼 수 있다.

## Skipping Operators
1. .skip
이 연산자는 첫 번째 요소부터 n개의 요소를 건너뛰고 싶을 때 사용한다.

```swift
let observer = Observable.of(1,2,3,4,5,6,7,8,9,10)
let disposeBag = DisposeBag()

observer.skip(5)
   .subscribe({ (value) in
       print(value)
   })
   .disposed(by: disposeBag)
   
// next(6)
// next(7)
// next(8)
// next(9)
// next(10)
// completed

위 코드에서 보면 .skip(5)를 사용해서 1~10의 요소에서 첫 요소(1)부터 5개의 요소(5까지)를 건너 뛴 6부터 출력되는 모습을 볼 수 있습니다.

  1. .skipWhile
    .skip은 단순히 몇 개의 요소를 건너뛰었다면 .skipWhile은 filter처럼 해당 수식에
    true인 요소들은 skip을하고 false인 요소를 방출하는데 false 이후로 true인 값들도 방출한다. 밑에 코드를 보면 더 쉽게 이해할 수 있다.
let observer = Observable.of(2,2,3,4,2,5,6)
let disposeBag = DisposeBag()

observer.skipWhile({ (value) -> Bool in
    value % 2 == 0
})
    .subscribe({ (value) in
        print(value)
    })
    .disposed(by: disposeBag)

// next(3)
// next(4)
// next(2)
// next(5)
// next(6)
// completed

(2,2,3,4,2,5,6) 요소에서skipWhile({ (value) -> Bool in value % 2 == 0 }) 수식을 만나게 되면 앞에 2개의 2는 true이기 때문에 skip이 이루어지고 3은 false다. 그래서 방출이 되고 이 이후로는 true여도 방출이 돼서 출력이 된다.

  1. .skipUntil
    매개변수로 들어가있는 Observable에서 이벤트가 방출하기 전까지는 skip하고 방출된 이후로 이벤트를 구독자에게 전달한다.
let disposebag = DisposeBag()
let subject = PublishSubject<Int>()
let skipSubject = PublishSubject<Int>()

subject.skipUntil(skipSubject)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposebag)

subject.onNext(1)
subject.onNext(2)

skipSubject.onNext(10)

subject.onNext(3)

// 3

skipSubject가 onNext하기 전에 방출한 1,2 이벤트는 방출되지 않고 그 이후로 방출한 3 이벤트만 출력된 모습을 볼 수 있다.

Taking Operators

  1. .take
    skip과는 반대로 뜻 그대로 가져오는 연산자이다. 코드를 보면
let disposebag = DisposeBag()
let observer = Observable.of(1,2,3,4,5)

observer.take(3)
    .subscribe({ (value) in
        print(value)
    })
    .disposed(by: disposebag)
    
// next(1)
// next(2)
// next(3)
// completed

(1,2,3,4,5) 요소 중에서 .take연산자를 통해서 3개의 요소만 가져온다고 해서 (1,2,3) 요소만 출력이 된 모습을 볼 수 있습니다.

  1. .takeWhile
    .take가 .skip과 반대였다면 .takeWhile은 .skipWhile의 반대처럼 동작한다.
let disposebag = DisposeBag()
let observer = Observable.of(2,4,3,5,6)

observer.takeWhile({ (value) -> Bool in
        value % 2 == 0
})
    .subscribe({ (value) in
        print(value)
    })
    .disposed(by: disposebag)

// next(2)
// next(4)
// completed

주어진 수식에 true인 값을 출력하고 false인 값부터 출력하지 않는다.

  1. .enumerated
    요소들을 인덱스와 함께 표현하고 싶을 때 사용한다.
let disposebag = DisposeBag()
let observer = Observable.of(2,4,3,5,6)

observer
    .enumerated()
    .takeWhile({ index, value -> Bool in
        value % 2 == 0
})
    .subscribe({ (value) in
        print(value)
    })
    .disposed(by: disposebag)

// next((index: 0, element: 2))
// next((index: 1, element: 4))
completed

takeWhile에서의 출력 값을 인덱스와 함께 출력한 모습을 볼 수 있다.

  1. .takeUntil
    .skipUntil과 반대로 수행한다.
let disposebag = DisposeBag()
let subject = PublishSubject<Int>()
let takeSubject = PublishSubject<Int>()

subject.takeUntil(takeSubject)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposebag)

subject.onNext(1)
subject.onNext(2)

takeSubject.onNext(10)

subject.onNext(3)

// 1
// 2

위 코드처럼 .skipUntil과 반대로 다른 observer가 이벤트를 방출하기 전까지 방출된 이벤트를 구독자에게 전달한다.

Distinct Operators

  1. .distinctUntilChanged
    중복돼서 방출되는 이벤트를 막아주는 역할을 한다.
let disposebag = DisposeBag()

Observable.of(1,2,3,3,4)
    
    .distinctUntilChanged()
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposebag)
    
// 1
// 2
// 3
// 4

출력에서 중복되는 3요소를 1번만 출력한 모습을 볼 수 있다. 또한 이 안에다가 수식을 넣어서 커스텀된 연산자를 만들 수 있다.

0개의 댓글