如何在Swift中同时遍历三个及以上数组?
Swift中遍历三个及以上数组的方法
好问题!咱们都知道Swift里用zip能轻松遍历两个数组,但碰到三个甚至更多数组的时候,直接用zip就不够用了,这里给你分享几种实用的解决办法:
1. 嵌套使用原生zip
如果只是偶尔处理三个数组,嵌套zip是最省事的办法,不用写额外工具代码。原理就是先把前两个数组zip成一个元组序列,再把这个序列和第三个数组zip起来,遍历的时候逐层解构元组就行:
let numbers = [1, 2, 3, 4] let letters = ["a", "b", "c", "d"] let flags = [true, false, true, false] // 三层解构对应三个数组的元素 for ((num, letter), flag) in zip(zip(numbers, letters), flags) { print("数字:\(num),字母:\(letter),标记:\(flag)") }
不过要注意,要是数组数量超过三个,嵌套的层数会越来越多,代码可读性会下降,这种情况更推荐下面的方法。
2. 自定义多序列zip函数
如果经常需要遍历三个及以上数组,最好自己封装一个通用的zip工具,比如先写一个支持三个序列的zip3:
// 自定义支持三个序列的zip函数 func zip3<S1: Sequence, S2: Sequence, S3: Sequence>( _ sequence1: S1, _ sequence2: S2, _ sequence3: S3 ) -> Zip3Sequence<S1, S2, S3> { // 定义内部序列结构 struct Zip3Sequence<Seq1: Sequence, Seq2: Sequence, Seq3: Sequence>: Sequence { let seq1: Seq1 let seq2: Seq2 let seq3: Seq3 // 生成迭代器 func makeIterator() -> Zip3Iterator<Seq1, Seq2, Seq3> { Zip3Iterator( it1: seq1.makeIterator(), it2: seq2.makeIterator(), it3: seq3.makeIterator() ) } } // 定义迭代器 struct Zip3Iterator<Iter1: IteratorProtocol, Iter2: IteratorProtocol, Iter3: IteratorProtocol>: IteratorProtocol { var it1: Iter1 var it2: Iter2 var it3: Iter3 mutating func next() -> (Iter1.Element, Iter2.Element, Iter3.Element)? { // 同时获取三个迭代器的下一个元素,只要有一个为空就停止 guard let elem1 = it1.next(), let elem2 = it2.next(), let elem3 = it3.next() else { return nil } return (elem1, elem2, elem3) } } return Zip3Sequence(seq1: sequence1, seq2: sequence2, seq3: sequence3) }
使用的时候就像原生zip一样直观:
for (num, letter, flag) in zip3(numbers, letters, flags) { print("数字:\(num),字母:\(letter),标记:\(flag)") }
要是需要支持四个数组,只需要照着这个结构扩展成zip4就行,逻辑完全一致——增加一个序列参数和对应的迭代器处理逻辑。
注意事项
不管用哪种方法,遍历的终止条件都是所有数组中最短的那个遍历完成,这和原生zip的行为保持一致,避免出现数组越界的问题。
内容的提问来源于stack exchange,提问作者johanjohansson
相关产品推荐
相关产品推荐

