@@ -35,66 +35,216 @@ extension Sequence {
3535 /// sequence.
3636 ///
3737 /// - Complexity: O(*n*), where `n` is the length of the shorter sequence.
38+ @inlinable
3839 public func includes< T: Sequence > (
3940 sorted other: T ,
4041 sortedBy areInIncreasingOrder: ( Element , Element ) throws -> Bool
4142 ) rethrows -> Bool
4243 where T. Element == Element {
43- // Originally, there was a function that evaluated the two sequences'
44- // elements with respect to having elements exclusive to the receiver,
45- // elements exclusive to `other`, and shared elements. But this function
46- // only needs to know when an element that is exclusive to the `other` is
47- // found. So, that function's guts were ripped out and repurposed.
44+ return try ! overlap( withSorted: other, bailAfterOtherExclusive: true ,
45+ sortedBy: areInIncreasingOrder) . elementsFromOther!
46+ }
47+ }
48+
49+ extension Sequence where Element: Comparable {
50+ /// Assuming that this sequence and the given sequence are sorted,
51+ /// determine whether the given sequence is contained within this one.
52+ ///
53+ /// let base = [0, 1, 2, 3, 6, 6, 7, 8, 9]
54+ /// assert(base.includes(sorted: [1, 2, 6, 7, 8]))
55+ /// assert(!base.includes(sorted: [1, 2, 5, 7, 8]))
56+ ///
57+ /// The elements of the argument need not be contiguous in the receiver.
58+ ///
59+ /// - Precondition: Both the receiver and `other` must be sorted.
60+ /// At least one of the involved sequences must be finite.
61+ ///
62+ /// - Parameter other: The sequence that is compared against the receiver.
63+ /// - Returns: Whether the entirety of `other` is contained within this
64+ /// sequence.
65+ ///
66+ /// - Complexity: O(*n*), where `n` is the length of the shorter sequence.
67+ @inlinable
68+ public func includes< T: Sequence > ( sorted other: T ) -> Bool
69+ where T. Element == Element {
70+ return includes ( sorted: other, sortedBy: < )
71+ }
72+ }
73+
74+ //===----------------------------------------------------------------------===//
75+ // MARK: - Sequence.overlap(withSorted:sortedBy:)
76+ //-------------------------------------------------------------------------===//
77+
78+ extension Sequence {
79+ /// Assuming that this sequence and the given sequence are sorted according
80+ /// to the given predicate, check if the sequences have overlap and/or
81+ /// exclusive elements.
82+ ///
83+ /// let base = [9, 8, 7, 6, 6, 3, 2, 1, 0]
84+ /// let test1 = base.overlap(withSorted: [8, 7, 6, 2, 1], sortedBy: >)
85+ /// let test2 = base.overlap(withSorted: [8, 7, 5, 2, 1], sortedBy: >)
86+ /// assert(test1.elementsFromSelf!)
87+ /// assert(test1.sharedElements!)
88+ /// assert(!test1.elementsFromOther!)
89+ /// assert(test2.elementsFromSelf!)
90+ /// assert(test2.sharedElements!)
91+ /// assert(test2.elementsFromOther!)
92+ ///
93+ /// - Precondition: Both the receiver and `other` must be sorted according to
94+ /// `areInIncreasingOrder`,
95+ /// which must be a strict weak ordering over its arguments.
96+ /// Either the receiver, `other`, or both must be finite.
97+ ///
98+ /// - Parameters:
99+ /// - other: The sequence that is compared against the receiver.
100+ /// - areInIncreasingOrder: The sorting criteria.
101+ /// - bailAfterSelfExclusive: Indicate that this function should abort as
102+ /// soon as one element that is exclusive to this sequence is found.
103+ /// If not given, defaults to `false`.
104+ /// - bailAfterShared: Indicate that this function should abort as soon as
105+ /// an element that both sequences share is found.
106+ /// If not given, defaults to `false`.
107+ /// - bailAfterOtherExclusive: Indicate that this function should abort as
108+ /// soon as one element that is exclusive to `other` is found.
109+ /// If not given, defaults to `false`.
110+ /// - Returns: A tuple of three `Bool` members indicating whether there are
111+ /// elements exclusive to `self`,
112+ /// there are elements shared between the sequences,
113+ /// and there are elements exclusive to `other`.
114+ /// If a member is `true`,
115+ /// then at least one element in that category exists.
116+ /// If a member is `false`,
117+ /// then there are no elements in that category.
118+ /// If a member is `nil`,
119+ /// then the function aborted before its category's status could be
120+ /// determined.
121+ ///
122+ /// - Complexity: O(*n*), where `n` is the length of the shorter sequence.
123+ public func overlap< T: Sequence > (
124+ withSorted other: T ,
125+ bailAfterSelfExclusive: Bool = false ,
126+ bailAfterShared: Bool = false ,
127+ bailAfterOtherExclusive: Bool = false ,
128+ sortedBy areInIncreasingOrder: ( Element , Element ) throws -> Bool
129+ ) rethrows -> (
130+ elementsFromSelf: Bool ? ,
131+ sharedElements: Bool ? ,
132+ elementsFromOther: Bool ?
133+ )
134+ where T. Element == Element {
48135 var firstElement , secondElement : Element ?
49136 var iterator = makeIterator ( ) , otherIterator = other. makeIterator ( )
50- while true {
137+ var result : ( fromSelf: Bool ? , shared: Bool ? , fromOther: Bool ? )
138+ loop:
139+ while result != ( true , true , true ) {
51140 firstElement = firstElement ?? iterator. next ( )
52141 secondElement = secondElement ?? otherIterator. next ( )
53142 switch ( firstElement, secondElement) {
54- case let ( first? , second? ) where try areInIncreasingOrder ( first, second) :
55- // Found an element exclusive to `self`, move on.
143+ case let ( s? , o? ) where try areInIncreasingOrder ( s, o) :
144+ // Exclusive to self
145+ result. fromSelf = true
146+ guard !bailAfterSelfExclusive else { break loop }
147+
148+ // Move to the next element in self.
56149 firstElement = nil
57- case let ( first? , second? ) where try areInIncreasingOrder ( second, first) :
58- // Found an element exclusive to `other`.
59- return false
150+ case let ( s? , o? ) where try areInIncreasingOrder ( o, s) :
151+ // Exclusive to other
152+ result. fromOther = true
153+ guard !bailAfterOtherExclusive else { break loop }
154+
155+ // Move to the next element in other.
156+ secondElement = nil
60157 case ( _? , _? ) :
61- // Found a shared element, move on.
158+ // Shared
159+ result. shared = true
160+ guard !bailAfterShared else { break loop }
161+
162+ // Iterate to the next element for both sequences.
62163 firstElement = nil
63164 secondElement = nil
165+ case ( _? , nil ) :
166+ // Never bail, just finalize after finding an exclusive to self.
167+ result. fromSelf = true
168+ result. shared = result. shared ?? false
169+ result. fromOther = result. fromOther ?? false
170+ break loop
64171 case ( nil , _? ) :
65- // Found an element exclusive to `other`, and any remaining elements
66- // will be exclusive to `other`.
67- return false
68- default :
69- // The elements from `other` (and possibly `self` too) have been
70- // exhausted without disproving inclusion.
71- return true
172+ // Never bail, just finalize after finding an exclusive to other.
173+ result. fromSelf = result. fromSelf ?? false
174+ result. shared = result. shared ?? false
175+ result. fromOther = true
176+ break loop
177+ case ( nil , nil ) :
178+ // Finalize everything instead of bailing
179+ result. fromSelf = result. fromSelf ?? false
180+ result. shared = result. shared ?? false
181+ result. fromOther = result. fromOther ?? false
182+ break loop
72183 }
73184 }
185+ return ( result. fromSelf, result. shared, result. fromOther)
74186 }
75187}
76188
77189extension Sequence where Element: Comparable {
78190 /// Assuming that this sequence and the given sequence are sorted,
79- /// determine whether the given sequence is contained within this one .
191+ /// check if the sequences have overlap and/or exclusive elements .
80192 ///
81193 /// let base = [0, 1, 2, 3, 6, 6, 7, 8, 9]
82- /// assert(base.includes(sorted: [1, 2, 6, 7, 8]))
83- /// assert(!base.includes(sorted: [1, 2, 5, 7, 8]))
84- ///
85- /// The elements of the argument need not be contiguous in the receiver.
194+ /// let test1 = base.overlap(withSorted: [1, 2, 6, 7, 8])
195+ /// let test2 = base.overlap(withSorted: [1, 2, 5, 7, 8])
196+ /// assert(test1.elementsFromSelf!)
197+ /// assert(test1.sharedElements!)
198+ /// assert(!test1.elementsFromOther!)
199+ /// assert(test2.elementsFromSelf!)
200+ /// assert(test2.sharedElements!)
201+ /// assert(test2.elementsFromOther!)
86202 ///
87203 /// - Precondition: Both the receiver and `other` must be sorted.
88204 /// At least one of the involved sequences must be finite.
89205 ///
90- /// - Parameter other: The sequence that is compared against the receiver.
91- /// - Returns: Whether the entirety of `other` is contained within this
92- /// sequence.
206+ /// - Parameters:
207+ /// - other: The sequence that is compared against the receiver.
208+ /// - bailAfterSelfExclusive: Indicate that this function should abort as
209+ /// soon as one element that is exclusive to this sequence is found.
210+ /// If not given, defaults to `false`.
211+ /// - bailAfterShared: Indicate that this function should abort as soon as
212+ /// an element that both sequences share is found.
213+ /// If not given, defaults to `false`.
214+ /// - bailAfterOtherExclusive: Indicate that this function should abort as
215+ /// soon as one element that is exclusive to `other` is found.
216+ /// If not given, defaults to `false`.
217+ /// - Returns: A tuple of three `Bool` members indicating whether there are
218+ /// elements exclusive to `self`,
219+ /// elements shared between the sequences,
220+ /// and elements exclusive to `other`.
221+ /// If a member is `true`,
222+ /// then at least one element in that category exists.
223+ /// If a member is `false`,
224+ /// then there are no elements in that category.
225+ /// If a member is `nil`,
226+ /// then the function aborted before its category's status could be
227+ /// determined.
93228 ///
94229 /// - Complexity: O(*n*), where `n` is the length of the shorter sequence.
95230 @inlinable
96- public func includes< T: Sequence > ( sorted other: T ) -> Bool
231+ public func overlap< T: Sequence > (
232+ withSorted other: T ,
233+ bailAfterSelfExclusive: Bool = false ,
234+ bailAfterShared: Bool = false ,
235+ bailAfterOtherExclusive: Bool = false
236+ ) -> (
237+ elementsFromSelf: Bool ? ,
238+ sharedElements: Bool ? ,
239+ elementsFromOther: Bool ?
240+ )
97241 where T. Element == Element {
98- return includes ( sorted: other, sortedBy: < )
242+ return overlap (
243+ withSorted: other,
244+ bailAfterSelfExclusive: bailAfterSelfExclusive,
245+ bailAfterShared: bailAfterShared,
246+ bailAfterOtherExclusive: bailAfterOtherExclusive,
247+ sortedBy: <
248+ )
99249 }
100250}
0 commit comments