เริ่มต้น Reactive Programming ด้วย Combine Part6: Filtering Operator

Cocodev
Lotus’s IT
Published in
2 min readDec 18, 2023

Filtering operator เป็น operator ของ publisher สำหรับ filter data จาก publisher เดิมไปยัง publisher ใหม่

numbersA:  |----1----2----3----4----5-----------------------------|-->
opratoion: .filter { $0 % 2 == 0 }
numbersB: |---------2---------4----------------------------------|-->


time(s): |----|----|----|----|----|----|----|----|----|----|----|-->
0 1 2 3 4 5 6 7 8 9 10 11

1. filter(_:)

filter จะเป็นการ filter element ของ array เดิมด้วยเงื่อนไขที่กำหนด

func filter(_ isIncluded: @escaping (Self.Output) -> Bool) -> Publishers.Filter<Self>

example

let numbers: [Int] = [1, 2, 3, 4, 5]
cancellable = numbers.publisher
.filter { $0 % 2 == 0 }
.sink { print("\($0)", terminator: " ") }

// Prints: "2 4"

2. compactMap(_:)

compactMap จะเป็น operator ที่คล้ายกันกับ map เลย เพียงแต่ compactMap จะทำการ fillter ค่า nill ออก

func compactMap<T>(_ transform: @escaping (Self.Output) -> T?) -> Publishers.CompactMap<Self, T>

example

let numbers = (0...5)
let romanNumeralDict: [Int : String] =
[1: "I", 2: "II", 3: "III", 5: "V"]


cancellable = numbers.publisher
.compactMap { romanNumeralDict[$0] }
.sink { print("\($0)", terminator: " ") }


// Prints: "I II III V"

3. removeDuplicates(by:)

removeDuplicates จะเป็น operator ที่ fillter ข้อมูลที่ซ้ำกันออกไปตามเงื่อนไง

func removeDuplicates(by predicate: @escaping (Self.Output, Self.Output) -> Bool) -> Publishers.RemoveDuplicates<Self>

example

struct Point {
let x: Int
let y: Int
}


let points = [Point(x: 0, y: 0), Point(x: 0, y: 1),
Point(x: 1, y: 1), Point(x: 2, y: 1)]
cancellable = points.publisher
.removeDuplicates { prev, current in
// Considers points to be duplicate if the x coordinate
// is equal, and ignores the y coordinate
prev.x == current.x
}
.sink { print("\($0)", terminator: " ") }


// Prints: Point(x: 0, y: 0) Point(x: 1, y: 1) Point(x: 2, y: 1)

4. replaceEmpty(with:)

replaceEmpty คือการเช็คว่า publisher data empty หรือไม่ และถ้าไม่มันจะ replace ค่าจาก operator ของมัน เช่น replace ด้วย 1

func replaceEmpty(with output: Self.Output) -> Publishers.ReplaceEmpty<Self>

example

let otherNumbers: [Double] = []
let cancellable3 = otherNumbers.publisher
.replaceEmpty(with: 1.0)
.sink { print("\($0)", terminator: " ") }

// Prints: 1.0

replaceError(with:)

replaceError คือการ replace error ที่เราไม่ต้องการให้เป็นค่าใดๆที่ต้องการ

func replaceError(with output: Self.Output) -> Publishers.ReplaceError<Self>

example

เช่น replace MyError ให้เป็นค่า “(replacement element)”

struct MyError: Error {}
let fail = Fail<String, MyError>(error: MyError())
cancellable = fail
.replaceError(with: "(replacement element)")
.sink(
receiveCompletion: { print ("\($0)") },
receiveValue: { print ("\($0)", terminator: " ") }
)


// Prints: "(replacement element) finished".

tryFilter(_:) tryCompactMap(_:) และ tryRemoveDuplicates(by:) เป็น operator ที่ทำงานเหมือนกับข้างต้น แต่รองรับการ throw exception

Next part: Reactive Programming ด้วย Combine Part7- Mapping Operator

--

--