Zip3Sequence.swift (6396B)
1 /// Copyright 2016 Alexander Momchilov 2 /// 3 /// Licensed under the Apache License, Version 2.0 (the "License"); 4 /// you may not use this file except in compliance with the License. 5 /// You may obtain a copy of the License at 6 /// 7 /// http://www.apache.org/licenses/LICENSE-2.0 8 /// 9 /// Unless required by applicable law or agreed to in writing, software 10 /// distributed under the License is distributed on an "AS IS" BASIS, 11 /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 /// See the License for the specific language governing permissions and limitations under the License. 13 14 /// Creates a sequence of tuples built out of 3 underlying sequences. 15 /// 16 /// In the `Zip3Sequence` instance returned by this function, the elements of 17 /// the *i*th tuple are the *i*th elements of each underlying sequence. The 18 /// following example uses the `zip(_:_:)` function to iterate over an array 19 /// of strings and a countable range at the same time: 20 /// 21 /// let words = ["one", "two", "three", "four"] 22 /// let numbers = 1...4 23 /// 24 /// for (word, number) in zip(words, numbers) { 25 /// print("\(word): \(number)") 26 /// } 27 /// // Prints "one: 1" 28 /// // Prints "two: 2 29 /// // Prints "three: 3" 30 /// // Prints "four: 4" 31 /// 32 /// If the 3 sequences passed to `zip(_:_:_:)` are different lengths, the 33 /// resulting sequence is the same length as the shortest sequence. In this 34 /// example, the resulting array is the same length as `words`: 35 /// 36 /// let naturalNumbers = 1...Int.max 37 /// let zipped = Array(zip(words, naturalNumbers)) 38 /// // zipped == [("one", 1), ("two", 2), ("three", 3), ("four", 4)] 39 /// 40 /// - Parameters: 41 /// - sequence1: The sequence or collection in position 1 of each tuple. 42 /// - sequence2: The sequence or collection in position 2 of each tuple. 43 /// - sequence3: The sequence or collection in position 3 of each tuple. 44 /// - Returns: A sequence of tuple pairs, where the elements of each pair are 45 /// corresponding elements of `sequence1` and `sequence2`. 46 public func zip<Sequence1 : Sequence, 47 Sequence2 : Sequence, 48 Sequence3 : Sequence 49 >( _ sequence1: Sequence1, 50 _ sequence2: Sequence2, 51 _ sequence3: Sequence3 52 ) -> Zip3Sequence< 53 Sequence1, 54 Sequence2, 55 Sequence3 56 > { 57 Zip3Sequence(_sequence1: sequence1, 58 _sequence2: sequence2, 59 _sequence3: sequence3) 60 } 61 62 /// An iterator for `Zip3Sequence`. 63 public struct Zip3Iterator<Iterator1 : IteratorProtocol, 64 Iterator2 : IteratorProtocol, 65 Iterator3 : IteratorProtocol 66 > : IteratorProtocol { 67 /// The type of element returned by `next()`. 68 public typealias Element = (Iterator1.Element, 69 Iterator2.Element, 70 Iterator3.Element) 71 72 /// Creates an instance around the underlying iterators. 73 internal init(_ iterator1: Iterator1, 74 _ iterator2: Iterator2, 75 _ iterator3: Iterator3 76 ) { 77 _baseStream1 = iterator1 78 _baseStream2 = iterator2 79 _baseStream3 = iterator3 80 } 81 82 /// Advances to the next element and returns it, or `nil` if no next element exists. 83 /// Once `nil` has been returned, all subsequent calls return `nil`. 84 public mutating func next() -> Element? { 85 // The next() function needs to track if it has reached the end. If we 86 // didn't, and the first sequence is longer than the second, then when we 87 // have already exhausted the second sequence, on every subsequent call to 88 // next() we would consume and discard one additional element from the 89 // first sequence, even though next() had already returned nil. 90 91 if _reachedEnd { 92 return nil 93 } 94 95 guard let element1 = _baseStream1.next(), 96 let element2 = _baseStream2.next(), 97 let element3 = _baseStream3.next() 98 else { 99 _reachedEnd = true 100 return nil 101 } 102 103 return (element1, element2, element3) 104 } 105 106 internal var _baseStream1: Iterator1 107 internal var _baseStream2: Iterator2 108 internal var _baseStream3: Iterator3 109 internal var _reachedEnd: Bool = false 110 } 111 112 /// A sequence of pairs built out of two underlying sequences. 113 /// 114 /// In a `Zip3Sequence` instance, the elements of the *i*th pair are the *i*th 115 /// elements of each underlying sequence. To create a `Zip3Sequence` instance, 116 /// use the `zip(_:_:_:)` function. 117 /// 118 /// The following example uses the `zip(_:_:)` function to iterate over an 119 /// array of strings and a countable range at the same time: 120 /// 121 /// let words = ["one", "two", "three", "four"] 122 /// let numbers = 1...4 123 /// 124 /// for (word, number) in zip(words, numbers) { 125 /// print("\(word): \(number)") 126 /// } 127 /// // Prints "one: 1" 128 /// // Prints "two: 2 129 /// // Prints "three: 3" 130 /// // Prints "four: 4" 131 /// 132 /// - SeeAlso: `zip(_:_:_:)` 133 public struct Zip3Sequence<Sequence1 : Sequence, 134 Sequence2 : Sequence, 135 Sequence3 : Sequence> : Sequence { 136 137 public typealias Stream1 = Sequence1.Iterator 138 public typealias Stream2 = Sequence2.Iterator 139 public typealias Stream3 = Sequence3.Iterator 140 141 /// A type whose instances can produce the elements of this sequence, in order. 142 public typealias Iterator = Zip3Iterator<Stream1, Stream2, Stream3> 143 144 @available(*, unavailable, renamed: "Iterator") 145 public typealias Generator = Iterator 146 147 /// Creates an instance that makes pairs of elements from `sequence1` and `sequence2`. 148 public // @testable 149 init(_sequence1 sequence1: Sequence1, 150 _sequence2 sequence2: Sequence2, 151 _sequence3 sequence3: Sequence3 152 ) { 153 _sequence1 = sequence1 154 _sequence2 = sequence2 155 _sequence3 = sequence3 156 } 157 158 /// Returns an iterator over the elements of this sequence. 159 public func makeIterator() -> Iterator { 160 Iterator(_sequence1.makeIterator(), 161 _sequence2.makeIterator(), 162 _sequence3.makeIterator()) 163 } 164 165 internal let _sequence1: Sequence1 166 internal let _sequence2: Sequence2 167 internal let _sequence3: Sequence3 168 }