# Combine-如何快速搜尋元素? -first(where:) last(where:) ## Overview ```swift let numbers = (1...10).publisher numbers .print("numbers") .first(where: { $0 % 3 == 0 }) .sink{ print($0) } .store(in: &subscriptions) ``` 從這個結果來看,會回傳第一個可以被3整除的元素。 ``` 3 ``` ```swift let numbers = (1...10).publisher numbers .print("numbers") .last(where: { $0 % 3 == 0 }) .sink{ print($0) } .store(in: &subscriptions) ``` 從這個結果來看,會回傳最後可以被3整除的元素。 ``` 9 ``` 這邊我們會認識 first(where:) 以及 last(where:)這兩個 operater。其實可以很簡單地從文字上認識他。first 就是從第一個元素開始往後搜尋;last 反之。可以關注的是後面的 where 是一個回傳 Bool 的閉包,當他回傳 true 時代表找到目標元素,找到目標元素會立刻終止搜尋。False 則會繼續搜尋。 ## first(where:) first 從前面的元素開始巡訪,從where 閉包當作尋找條件。 ```swift= let numbers = (1...10).publisher numbers .print() .first(where: { item in print(item) return item % 3 == 0 }) .sink{ print("find \($0)") } .store(in: &subscriptions) ``` ```swift= receive subscription: (1...10) request unlimited receive value: (1) 1 receive value: (2) 2 receive value: (3) 3 receive cancel find 3 ``` 從剛剛實驗得圖得知,當元素找到後,不會繼續尋訪,而是立刻終止。 ![](https://hackmd.io/_uploads/BJr8G1nfa.png) ## 發出 complete 之後才會運作。 因為operator無法知道publisher是否會在後續發出符合條件的值,因此operator必須了解完整的publisher範圍,才能確定滿足最後一個項目。 ```swift= let numbers = PassthroughSubject<Int, Never>() numbers .last(where: { $0 % 2 == 0 }) .sink(receiveCompletion: { _ in print("Completed") }, receiveValue: { print($0) }) .store(in: &subscriptions) numbers.send(1) numbers.send(2) numbers.send(3) numbers.send(4) numbers.send(5) numbers.send(completion: .finished) ``` ```swift= 4 Completed ```