Skip to content

Instantly share code, notes, and snippets.

@alltom
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alltom/df50ffe7a2b4e0537b04 to your computer and use it in GitHub Desktop.
Save alltom/df50ffe7a2b4e0537b04 to your computer and use it in GitHub Desktop.
Swift Challenge #2
// https://gist.github.com/Eiam8821/07a7372667879172e9df
enum TakeWhileState {
case Continuing(Int)
case Done
}
struct TakeWhileGenerator<T>: GeneratorType {
let sequence: TakeWhile<T>
var state: TakeWhileState
init(sequence: TakeWhile<T>) {
self.sequence = sequence
self.state = 0 < sequence.array.count ? .Continuing(0) : .Done
}
mutating func next() -> T? {
switch state {
case let .Continuing(index):
let item = sequence.array[index]
if sequence.condition(item) {
state = index + 1 < sequence.array.count ? .Continuing(index + 1) : .Done
return item
} else {
state = .Done
return nil
}
case .Done:
return nil
}
}
}
struct TakeWhile<T>: SequenceType {
let array: [T]
let condition: T -> Bool
init(array: [T], condition: T -> Bool) {
self.array = array
self.condition = condition
}
func generate() -> TakeWhileGenerator<T> {
return TakeWhileGenerator(sequence: self)
}
}
extension Array {
func takeWhile(condition: Element -> Bool) -> [Element] {
return Array(TakeWhile(array: self, condition: condition))
}
}
for item in (TakeWhile(array: [1, 2, 3, 4, 5]) { $0 < 3 }) {
println(item)
}
@drewag
Copy link

drewag commented Aug 5, 2014

Array itself is a Sequence so you can use its generator instead of dealing with its indexes and worrying about state. Once you do that, you can make TakeWhile even more generic if you take any sequence and use the same generator logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment