1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// Creates a sequence of pairs built out of two underlying sequences.
///
/// In the `Zip2Sequence` instance returned by this function, the elements of
/// the *i*th pair are the *i*th elements of each underlying sequence. The
/// following example uses the `zip(_:_:)` function to iterate over an array
/// of strings and a countable range at the same time:
///
/// let words = ["one", "two", "three", "four"]
/// let numbers = 1...4
///
/// for (word, number) in zip(words, numbers) {
/// print("\(word): \(number)")
/// }
/// // Prints "one: 1"
/// // Prints "two: 2"
/// // Prints "three: 3"
/// // Prints "four: 4"
///
/// If the two sequences passed to `zip(_:_:)` are different lengths, the
/// resulting sequence is the same length as the shorter sequence. In this
/// example, the resulting array is the same length as `words`:
///
/// let naturalNumbers = 1...Int.max
/// let zipped = Array(zip(words, naturalNumbers))
/// // zipped == [("one", 1), ("two", 2), ("three", 3), ("four", 4)]
///
/// - Parameters:
/// - sequence1: The first sequence or collection to zip.
/// - sequence2: The second sequence or collection to zip.
/// - Returns: A sequence of tuple pairs, where the elements of each pair are
/// corresponding elements of `sequence1` and `sequence2`.
@inlinable // generic-performance
public func zip<Sequence1, Sequence2>(
_ sequence1: Sequence1, _ sequence2: Sequence2
) -> Zip2Sequence<Sequence1, Sequence2> {
return Zip2Sequence(sequence1, sequence2)
}
/// A sequence of pairs built out of two underlying sequences.
///
/// In a `Zip2Sequence` instance, the elements of the *i*th pair are the *i*th
/// elements of each underlying sequence. To create a `Zip2Sequence` instance,
/// use the `zip(_:_:)` function.
///
/// The following example uses the `zip(_:_:)` function to iterate over an
/// array of strings and a countable range at the same time:
///
/// let words = ["one", "two", "three", "four"]
/// let numbers = 1...4
///
/// for (word, number) in zip(words, numbers) {
/// print("\(word): \(number)")
/// }
/// // Prints "one: 1"
/// // Prints "two: 2"
/// // Prints "three: 3"
/// // Prints "four: 4"
@frozen // generic-performance
public struct Zip2Sequence<Sequence1: Sequence, Sequence2: Sequence> {
@usableFromInline // generic-performance
internal let _sequence1: Sequence1
@usableFromInline // generic-performance
internal let _sequence2: Sequence2
/// Creates an instance that makes pairs of elements from `sequence1` and
/// `sequence2`.
@inlinable // generic-performance
internal init(_ sequence1: Sequence1, _ sequence2: Sequence2) {
(_sequence1, _sequence2) = (sequence1, sequence2)
}
}
extension Zip2Sequence {
/// An iterator for `Zip2Sequence`.
@frozen // generic-performance
public struct Iterator {
@usableFromInline // generic-performance
internal var _baseStream1: Sequence1.Iterator
@usableFromInline // generic-performance
internal var _baseStream2: Sequence2.Iterator
@usableFromInline // generic-performance
internal var _reachedEnd: Bool = false
/// Creates an instance around a pair of underlying iterators.
@inlinable // generic-performance
internal init(
_ iterator1: Sequence1.Iterator,
_ iterator2: Sequence2.Iterator
) {
(_baseStream1, _baseStream2) = (iterator1, iterator2)
}
}
}
extension Zip2Sequence.Iterator: IteratorProtocol {
/// The type of element returned by `next()`.
public typealias Element = (Sequence1.Element, Sequence2.Element)
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
@inlinable // generic-performance
public mutating func next() -> Element? {
// The next() function needs to track if it has reached the end. If we
// didn't, and the first sequence is longer than the second, then when we
// have already exhausted the second sequence, on every subsequent call to
// next() we would consume and discard one additional element from the
// first sequence, even though next() had already returned nil.
if _reachedEnd {
return nil
}
guard let element1 = _baseStream1.next(),
let element2 = _baseStream2.next() else {
_reachedEnd = true
return nil
}
return (element1, element2)
}
}
extension Zip2Sequence: Sequence {
public typealias Element = (Sequence1.Element, Sequence2.Element)
/// Returns an iterator over the elements of this sequence.
@inlinable // generic-performance
public __consuming func makeIterator() -> Iterator {
return Iterator(
_sequence1.makeIterator(),
_sequence2.makeIterator())
}
@inlinable // generic-performance
public var underestimatedCount: Int {
return Swift.min(
_sequence1.underestimatedCount,
_sequence2.underestimatedCount
)
}
}
extension Zip2Sequence: Sendable where Sequence1: Sendable,
Sequence2: Sendable { }
extension Zip2Sequence.Iterator: Sendable where Sequence1.Iterator: Sendable,
Sequence2.Iterator: Sendable { }
|