zip
在Swift里是一個全局函數(shù),參數(shù)接收兩個Sequence
仁热,返回一個可以遍歷兩個sequence
的Element
的元組Zip2Sequence
.
使用舉例
目前項目中有一個視圖模型ViewModel
有title
和image
屬性,用來給視圖賦值用。
struct ViewModel {
let title: String
let image: UIImage
}
這里面的title和image都是直接在本地進行配置死嗦,總共有5個。
第一種常規(guī)方式我們可以這樣
let viewModel1 = ViewModel(title: "1", image: image1)
let viewModel2 = ViewModel(title: "2", image: image2)
let viewModel3 = ViewModel(title: "3", image: image3)
let viewModel4 = ViewModel(title: "4", image: image4)
let viewModel5 = ViewModel(title: "5", image: image5)
let viewModels = [viewModel1, xxx]
但是調(diào)用五次構(gòu)造方法不是個好的方式粒氧,若是viewModel
將來擴展一個參數(shù)越除,我們5個構(gòu)造函數(shù)都需要更改。數(shù)據(jù)的配置與構(gòu)建沒有分層
第二種方式:
let titles: [String] = ["1", "2", "3", "4", "5"]
let images: [UIImage] = [image1, image2,image3,image4,image5]
var viewModels: [ViewModel] = []
for i in 0 ..< titles.count {
viewModels.append(ViewModel(title: titles[i], image: images[i])
}
解決了第一種方式提到的問題.配置數(shù)據(jù)和構(gòu)建模型是分開的. 構(gòu)造方法也只調(diào)用了一次.但是使用下標從數(shù)組里取值還有更優(yōu)雅的方式.
使用zip
let titles: [String] = ["1", "2", "3", "4", "5"]
let images: [UIImage] = [image1, image2,image3,image4,image5]
let viewModels = zip(titles, images).map(ViewModel.init)
除了元素的配置,構(gòu)建viewModel
數(shù)組只需要一行代碼就搞定了.
zip
方法在兩個Sequence
中其中一個沒有next元素了就進行了停止.
那么如果ViewModel
不是有兩個元素而是三個呢. 可以選擇zip
嵌套或者ViewModel
屬性里用元組的方式.
zip(array1, zip(array2, array3)).map {
ViewModel.init(a: $0, b: $1.0, c: $1.1)
}
實現(xiàn)
核心就是zip
函數(shù)返回的Zip2Sequence
序列的Iterator
方法摘盆,也就是next
函數(shù).
思路就是將兩個sequence
全都保存下來,迭代的時候取兩個sequence
的迭代方法,只要有一個返回了nil就返回nil翼雀,取到值就包到元組里進行返回,比較簡單.
class Zip2Sequence<S1: MySequence, S2: MySequence>: MySequence {
typealias Element = (S1.Element, S2.Element)
typealias Iterator = Interator
let _sequence1: S1
let _sequence2: S2
init(base1: S1, base2: S2) {
_sequence1 = base1
_sequence2 = base2
}
func makeIterator() -> Interator {
Interator(it1: _sequence1.makeIterator(), it2: _sequence2.makeIterator())
}
}
extension Zip2Sequence {
struct Interator: MyIteratorProtocol {
var it1: S1.Iterator
var it2: S2.Iterator
init(it1: S1.Iterator, it2: S2.Iterator) {
(self.it1, self.it2) = (it1, it2)
}
mutating func next() -> (S1.Element, S2.Element)? {
guard let e1 = it1.next(), let e2 = it2.next() else {
return nil
}
return (e1, e2)
}
}
}
其實根據(jù)實現(xiàn)骡澈,我們也比較容易實現(xiàn)一個Zip3Sequence
,或者可以接收一個Sequence
數(shù)組的zip.