For a final challenge, here is what you can do after the book. The Standard Library has methods for splitting a string over a single character, or a function that takes a single character and returns a Boolean. However, it doesn't have any methods for splitting a string over a substring, or doing it lazily.
Create a new method, which can be used on lazy strings and substrings, and takes a separator (String) and optionally String.CompareOptions
and Locale
, and returns a lazy sequence of the ranges between each occurrence of the separator in the original string/substring.
There are several ways of achieving this. The following hints describe one solution which uses some of the methods we have created in this course. Try and see if you can complete this by using as few hints as possible.
Hints:
allranges
method we created in Lesson 6.lowerBound
and upperBound
of the ranges of the separators into a sequence of indices.private func joinSequences<S1,S2>(_ s1: S1, _ s2: S2) -> UnfoldSequence<S1.Element, (Optional<S1.Iterator>, S2.Iterator)> where S1:Sequence, S2:Sequence, S1.Element == S2.Element { return sequence(state: (Optional(s1.makeIterator()), s2.makeIterator())) { seqs -> S1.Element? in guard let _ = seqs.0 else { return seqs.1.next() } return seqs.0?.next() ?? { seqs.0 = nil; return seqs.1.next() }() } } public func +<S1,S2>(s1: S1, s2: S2) -> UnfoldSequence<S1.Element, (Optional<S1.Iterator>, S2.Iterator)> where S1:Sequence, S2:Sequence, S1.Element == S2.Element { return joinSequences(s1, s2) } public func +<S1,S2>(s1: S1, s2: S2) -> LazySequence<UnfoldSequence<S1.Element, (Optional<S1.Iterator>, S2.Iterator)>> where S1:Sequence, S2:LazySequenceProtocol, S1.Element == S2.Element { return joinSequences(s1, s2).lazy } public func +<S1,S2>(s1: S1, s2: S2) -> LazySequence<UnfoldSequence<S1.Element, (Optional<S1.Iterator>, S2.Iterator)>> where S1:LazySequenceProtocol, S2:Sequence, S1.Element == S2.Element { return joinSequences(s1, s2).lazy }
group2
method from Lesson 6.