Implement handling of allowEmptySlices, add LazyCollectionType.split .
Proper unit tests, also of standard library CollectionType.split, to ensure they do the same.
This commit is contained in:
@@ -5,29 +5,43 @@
|
||||
*
|
||||
*/
|
||||
|
||||
public struct LazySplitGenerator <Base: CollectionType where Base.Generator.Element: Equatable, Base.SubSequence: CollectionType,
|
||||
Base.SubSequence.Generator.Element==Base.Generator.Element, Base.SubSequence==Base.SubSequence.SubSequence>: GeneratorType {
|
||||
public struct LazySplitSequence <Base: CollectionType where Base.Generator.Element: Equatable, Base.SubSequence: CollectionType,
|
||||
Base.SubSequence.Generator.Element==Base.Generator.Element, Base.SubSequence==Base.SubSequence.SubSequence>: GeneratorType, LazySequenceType {
|
||||
|
||||
private var remaining: Base.SubSequence?
|
||||
private let separator: Base.Generator.Element
|
||||
private let allowEmptySlices: Bool
|
||||
|
||||
public init (base: Base, separator: Base.Generator.Element) {
|
||||
public init (base: Base, separator: Base.Generator.Element, allowEmptySlices: Bool = false) {
|
||||
self.separator = separator
|
||||
self.remaining = base[base.startIndex..<base.endIndex]
|
||||
self.allowEmptySlices = allowEmptySlices
|
||||
}
|
||||
|
||||
public mutating func next() -> Base.SubSequence? {
|
||||
guard let remaining = self.remaining else { return nil }
|
||||
let (head,tail) = remaining.splitOnce(separator)
|
||||
let (head,tail) = remaining.splitOnce(separator, allowEmptySlices: allowEmptySlices)
|
||||
self.remaining = tail
|
||||
return head
|
||||
}
|
||||
|
||||
public func generate() -> LazySplitSequence { return self }
|
||||
}
|
||||
|
||||
extension CollectionType where Generator.Element: Equatable {
|
||||
extension CollectionType where Generator.Element: Equatable, SubSequence: CollectionType, SubSequence.Generator.Element==Generator.Element, SubSequence==SubSequence.SubSequence {
|
||||
|
||||
public func splitOnce (separator: Generator.Element, allowEmptySlices: Bool = false) -> (head: SubSequence, tail: SubSequence?) {
|
||||
guard let nextindex = indexOf(separator) else { return (self[startIndex..<endIndex], nil) }
|
||||
return (self[startIndex..<nextindex], self[nextindex.successor()..<endIndex])
|
||||
let head = self[startIndex..<nextindex]
|
||||
let tail = self[nextindex.successor()..<endIndex]
|
||||
if !allowEmptySlices && head.isEmpty { return tail.splitOnce(separator, allowEmptySlices: false) }
|
||||
return (head, tail.isEmpty && !allowEmptySlices ? nil : tail)
|
||||
}
|
||||
}
|
||||
|
||||
extension LazyCollectionType where Elements.Generator.Element: Equatable, Elements.SubSequence: CollectionType, Elements.SubSequence.Generator.Element==Elements.Generator.Element, Elements.SubSequence==Elements.SubSequence.SubSequence {
|
||||
|
||||
public func split (separator: Self.Elements.Generator.Element, allowEmptySlices: Bool = false) -> LazySplitSequence<Self.Elements> {
|
||||
return LazySplitSequence(base: self.elements, separator: separator, allowEmptySlices: allowEmptySlices)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,24 +11,69 @@ import XCTest
|
||||
|
||||
class LazySplitGenerator_Tests: XCTestCase {
|
||||
|
||||
func splitToArray (s: String) -> [String] {
|
||||
let g = LazySplitGenerator(base: s.characters, separator: " " as Character)
|
||||
return AnySequence {g} .map {String($0)}
|
||||
func lazySplitToArray (allowEmptySlices allowEmptySlices: Bool) (_ s: String) -> [String] {
|
||||
let seq: LazySplitSequence = s.characters.lazy.split("," as Character, allowEmptySlices: allowEmptySlices)
|
||||
return seq.map {String($0)}
|
||||
}
|
||||
|
||||
func testStrings () {
|
||||
XCTAssertEqual(splitToArray("abc def"), ["abc","def"])
|
||||
XCTAssertEqual(splitToArray(" a"), ["","a"])
|
||||
XCTAssertEqual(splitToArray("a "), ["a",""])
|
||||
XCTAssertEqual(splitToArray("a b"), ["a","","b"])
|
||||
func testStringsLazySplit_AllowingEmptySlices () {
|
||||
let split = lazySplitToArray(allowEmptySlices: true)
|
||||
|
||||
XCTAssertEqual(split("ab,c,de,f"), ["ab","c","de","f"])
|
||||
XCTAssertEqual(split(",a"), ["","a"])
|
||||
XCTAssertEqual(split("a,"), ["a",""])
|
||||
XCTAssertEqual(split("a,,b,,,c"), ["a","","b","","","c"])
|
||||
XCTAssertEqual(split(""), [""])
|
||||
XCTAssertEqual(split(","), ["",""])
|
||||
XCTAssertEqual(split("ab"), ["ab"])
|
||||
}
|
||||
|
||||
func splitIntsToArray (s: [Int]) -> [[Int]] {
|
||||
let g = LazySplitGenerator(base: s, separator: 0)
|
||||
return AnySequence {g} .map {Array($0)}
|
||||
func testCollectionTypeSplit_AllowingEmptySlices () {
|
||||
let split = {(s: String) -> [String] in
|
||||
s.characters.split(",", allowEmptySlices: true).map {String($0)}
|
||||
}
|
||||
|
||||
XCTAssertEqual(split("ab,c,de,f"), ["ab","c","de","f"])
|
||||
XCTAssertEqual(split(",a"), ["","a"])
|
||||
XCTAssertEqual(split("a,"), ["a",""])
|
||||
XCTAssertEqual(split("a,,b,,,c"), ["a","","b","","","c"])
|
||||
XCTAssertEqual(split(""), [""])
|
||||
XCTAssertEqual(split(","), ["",""])
|
||||
XCTAssertEqual(split("ab"), ["ab"])
|
||||
}
|
||||
|
||||
func testInts () {
|
||||
XCTAssertEqual(splitIntsToArray([1,2,0,4,0,6,7,8,9]), [[1,2],[4],[6,7,8,9]])
|
||||
func testStringsLazySplit_NoEmptySlices () {
|
||||
let split = lazySplitToArray(allowEmptySlices: false)
|
||||
|
||||
XCTAssertEqual(split("ab,c,de,f"), ["ab","c","de","f"])
|
||||
XCTAssertEqual(split(",a"), ["a"])
|
||||
XCTAssertEqual(split("a,"), ["a"])
|
||||
XCTAssertEqual(split("a,,b,,,c"), ["a","b","c"])
|
||||
XCTAssertEqual(split(""), [])
|
||||
XCTAssertEqual(split(","), [])
|
||||
XCTAssertEqual(split("ab"), ["ab"])
|
||||
}
|
||||
|
||||
func testCollectionTypeSplit_NoEmptySlices () {
|
||||
let split = {(s: String) -> [String] in
|
||||
s.characters.split(",", allowEmptySlices: false).map {String($0)}
|
||||
}
|
||||
|
||||
XCTAssertEqual(split("ab,c,de,f"), ["ab","c","de","f"])
|
||||
XCTAssertEqual(split(",a"), ["a"])
|
||||
XCTAssertEqual(split("a,"), ["a"])
|
||||
XCTAssertEqual(split("a,,b,,,c"), ["a","b","c"])
|
||||
XCTAssertEqual(split(""), [])
|
||||
XCTAssertEqual(split(","), [])
|
||||
XCTAssertEqual(split("ab"), ["ab"])
|
||||
}
|
||||
|
||||
func testIntsLazySplit_NoEmptySlices () {
|
||||
let split = {(s: [Int]) -> [[Int]] in
|
||||
s.lazy.split(0, allowEmptySlices: false).map {Array($0)}
|
||||
}
|
||||
|
||||
XCTAssertEqual(split([1,2,0,4,0,6,7,8,9]), [[1,2],[4],[6,7,8,9]])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user