So I'm a big fan of the method indexOf() on CollectionType:
extension CollectionType {
func indexOf(@noescape predicate: (Self.Generator.Element) -> Bool) -> Self.Index?
}
It's really useful for finding the first item in a collection that satisfies the closure:
let foo = 0...10
let firstItem = foo.indexOf { $0 > 5 }
Sure it's O(n), but sometimes you don't care or that's acceptable behavior. Now I'd also really like to have a corresponding lastIndexOf method, which would return the last item in the collection that satisfies the closure. But this doesn't seem to fit well with CollectionType as it is, as I think SequenceType.Generator only goes forward. And I think maybe _Incrementable might be a part of this too? It appears to only index forward as well.
Sure, I could always just do something this:
let lastItem = (foo.count - 1) - foo.reverse.indexOf { $0 < 5 }
But that seems like it would incur a performance penalty by reversing the array. What I really want is to actually iterate through the array in reverse, so that the performance is still just O(n). But I guess that means I can only ever do this where CollectionType.Index is RandomAccessIndexType? I mean, the reverse() method is only available in that case:
extension CollectionType where Index : RandomAccessIndexType {
func reverse() -> ReverseRandomAccessCollection<Self>
}
Or maybe I want BidirectionalIndexType?
Anyways I've got the simple implementation for Array:
extension Array {
func lastIndexOf(@noescape predicate: (Array.Generator.Element) -> Bool) -> Array.Index? {
for var i = self.endIndex-1; i >= self.startIndex; i-- {
if predicate(self[i]) {
return i
}
}
return nil
}
}
Right? But it seems like this should be accomplishable using just a protocol extension of CollectionType, without generating a reverse array. Presumably with some limitations on types. Anyone have a solution?