findfirst for iterator-defined collections

I would like to be able to use findfirst over a collection defined by an iterator. For example

findfirst(x->x==5, collect(Iterators.flatten((1:2,5:7)))) == 3

but there is no method for

findfirst(x->x==5, Iterators.flatten((1:2,5:7)))

Am I missing an idiomatic way to accomplish what I’d like without reifying the collection? If not, it might make a nice addition to IterTools. I’m using v0.7.0.

1 Like

I believe this should really be implemented in Base. If it were in IterTools, it would be considered type piracy.

2 Likes

What does the return value indicate? It’s not an index, since a general iterator cannot be indexed. So to use it, you would anyway need to collect your iterator in one way or another. Or your iterator should be indexable, in which case it could probably be a subtype of AbstractVector.

Anyway, given the function f that needs to evaluate to true, it’s as simple as this:

for (i,v) in enumerate(iterator)
   f(v) && return i
end
2 Likes

Good point Jutho. My use case was to check wheher some element of the collection satisfied a particular property so the better approach is to use any(predicate,collection) which does accept iterators.

Thanks!

1 Like

This has been raised a few times before, and a solution which has been proposed is to provide a (say) withlinearindices wrapper which would do as if the input iterator used linear indices starting from 1.

Thinking about it, it is already there is some sense:

first(Iterators.filter(x->x==5, Iterators.flatten((1:2,5:7))))
5

first(Iterators.filter(x->x[2]==5, enumerate(Iterators.flatten((1:2,5:7)))))
(3, 5)

Just define

getfirst = first∘Iterators.filter
2 Likes