Skip to content

Commit 650d9ba

Browse files
committed
Fix lazy sequence bug with separator count >= element count.
Because the array into which the lazy sequence iterator collected the subsequence elements was a member property, it had to be manually emptied before each invocation of `next`. Since there are multiple exit points from that method, there were multiple places that had to be done, and of course I missed at least one. This caused the last element of the base sequence to be repeated as necessary to make `sequenceLength` equal `separatorCount + 1`, in the case where the number of separators was equal to or great than the number of non-separators in the base sequence, and the last sequence element was a non-separator. Happily, it's not necessary for the subsequence array to be a member property of the iterator, and making it a local fixes this bug, in addition to being the right and proper thing to do.
1 parent 2819c44 commit 650d9ba

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed

Sources/Algorithms/LazySplitSequence.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ extension LazySplitSequence {
3333
internal let isSeparator: (Base.Element) -> Bool
3434
internal let maxSplits: Int
3535
internal let omittingEmptySubsequences: Bool
36-
internal var subsequence: Element = []
3736
internal var separatorCount = 0
3837
internal var sequenceLength = 0
3938

@@ -88,6 +87,7 @@ extension LazySplitSequence.Iterator: IteratorProtocol {
8887
/// // last split -> [], [], []
8988

9089
var currentElement = base.next()
90+
var subsequence: Element = []
9191

9292
while currentElement != nil {
9393
if separatorCount < maxSplits && isSeparator(currentElement!) {

Tests/SwiftAlgorithmsTests/LazySplitCollectionTests.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,24 @@ final class LazySplitCollectionTests: XCTestCase {
195195
let testResult = empty.lazy.split(separator: 42)
196196
XCTAssertEqualSequences(expectedResult, testResult)
197197
}
198+
199+
func testSepCountEqualOrMoreThanElemCount() {
200+
let nums = [0, 1, 0, 0, 2]
201+
let expectedResult = nums.split(separator: 0)
202+
let testResult = nums.lazy.split(separator: 0)
203+
XCTAssertEqualSequences(testResult, expectedResult)
204+
}
205+
206+
func testSepCountEqualOrMoreThanElemCountNotOmittingEmpty() {
207+
let nums = [0, 1, 0, 0, 2]
208+
let expectedResult = nums.split(
209+
separator: 0,
210+
omittingEmptySubsequences: false
211+
)
212+
let testResult = nums.lazy.split(
213+
separator: 0,
214+
omittingEmptySubsequences: false
215+
)
216+
XCTAssertEqualSequences(testResult, expectedResult)
217+
}
198218
}

Tests/SwiftAlgorithmsTests/LazySplitSequenceTests.swift

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,67 @@ final class LazySplitSequenceTests: XCTestCase {
8282
)
8383
XCTAssertEqualSequences(testResult, expectedResult)
8484
}
85+
86+
// Exercise the end-of-list logic to make sure we don't, for example, repeat
87+
// the last element when there are an equal or greater number of separators
88+
// than elements.
89+
func testSepCountEqualElemCount() {
90+
let nums = AnySequence([1, 0, 0, 2])
91+
let expectedResult = nums.split(separator: 0).map { Array($0) }
92+
let testResult = nums.lazy.split(separator: 0)
93+
XCTAssertEqualSequences(testResult, expectedResult)
94+
}
95+
96+
func testSepCountEqualElemCountNotOmittingEmpty() {
97+
let nums = AnySequence([1, 0, 0, 2])
98+
let expectedResult = nums.split(
99+
separator: 0,
100+
omittingEmptySubsequences: false
101+
).map { Array($0) }
102+
let testResult = nums.lazy.split(
103+
separator: 0,
104+
omittingEmptySubsequences: false
105+
)
106+
XCTAssertEqualSequences(testResult, expectedResult)
107+
}
108+
109+
func testSepCountMoreThanElemCountStartsWithSep() {
110+
let nums = AnySequence([0, 1, 0, 0, 2])
111+
let expectedResult = nums.split(separator: 0).map { Array($0) }
112+
let testResult = nums.lazy.split(separator: 0)
113+
XCTAssertEqualSequences(testResult, expectedResult)
114+
}
115+
116+
func testSepCountMoreThanElemCountStartsWithSepNotOmittingEmpty() {
117+
let nums = AnySequence([0, 1, 0, 0, 2])
118+
let expectedResult = nums.split(
119+
separator: 0,
120+
omittingEmptySubsequences: false
121+
).map { Array($0) }
122+
let testResult = nums.lazy.split(
123+
separator: 0,
124+
omittingEmptySubsequences: false
125+
)
126+
XCTAssertEqualSequences(testResult, expectedResult)
127+
}
128+
129+
func testSepCountMoreThanElemCountStartsWithElem() {
130+
let nums = AnySequence([1, 0, 0, 0, 0, 2, 0, 3])
131+
let expectedResult = nums.split(separator: 0).map { Array($0) }
132+
let testResult = nums.lazy.split(separator: 0)
133+
XCTAssertEqualSequences(testResult, expectedResult)
134+
}
135+
136+
func testSepCountMoreThanElemCountStartsWithElemNotOmittingEmpty() {
137+
let nums = AnySequence([1, 0, 0, 0, 0, 2, 0, 3])
138+
let expectedResult = nums.split(
139+
separator: 0,
140+
omittingEmptySubsequences: false
141+
).map { Array($0) }
142+
let testResult = nums.lazy.split(
143+
separator: 0,
144+
omittingEmptySubsequences: false
145+
)
146+
XCTAssertEqualSequences(testResult, expectedResult)
147+
}
85148
}

0 commit comments

Comments
 (0)