Replacement for find(all) on zip?


#1

In Julia 0.6, we could to

julia> find(x -> x[1] + x[2] > 0.5, zip(rand(10), rand(10)))

However, in Julia v1.0 this doesn’t work, because Base.Iterators.Zip2 has no keys:

julia> findall(x -> x[1] + x[2] > 0.5, zip(rand(10), rand(10)))
ERROR: MethodError: no method matching keys(::Base.Iterators.Zip2{Array{Float64,1},Array{Float64,1}})

Do we have a good replacement for this?


#2

Not really AFAIK. findall(rand(10) .+ rand(10) .> 0.5) should do the trick, but it allocates.

See this issue for the history.


#3
filter(x -> x[1] + x[2] > 0.5, collect(zip(rand(10), rand(10))))

Also, this generator is much better:

(x -> x[1] + x[2] > 0.5, zip(rand(10), rand(10)))

#4

Just do the find over the set of indices:

A, B = rand(10), rand(10)
findall(i->A[i]+B[i]>0.5, keys(A))

Actually, if you do this, you probably do want to use filter instead:

filter(i->A[i]+B[i]>0.5, keys(A))

as then you don’t need to worry about indexing back into your vector of indices.


#5

Sure, that’s my current workaround. But the collect is expensive in my use case, it’s a lot of data.


#6

Just do the find over the set of indices:

Unfortunately, the function comes from somewhere else and is supposed to operate on values, not indices.

Actually, if you do this, you probably do want to use filter instead:
as then you don’t need to worry about indexing back into your vector of indices.

Normally, I would, of course. But in this case, i want the indices: The result is a data selector for a another large dataset (big entries). Have to avoid copies, and data may be out-of-core.


#7

Compose it with getindex then.


#8

I’m filtering the keys of the collection, not the values. Even if it’s an opaque function, this should just work. You can also customize which kinds of keys you get back (linear or Cartesian), for example:

filter(i->f(A[i], B[i]), eachindex(A,B))

#9

Yes, that might work.