Type of array index?

using InvertedIndices
 function partition_vec1(v, thresh)
    idx_l = findall(<(thresh), v)
    (idx_l,  Not(idx_l))
  end

Interesting, but the use of Not(idx_l) is too much limited:

julia> v = rand(1:10, 10)
# . . . 
julia> a, b = partition_vec1(v, 7)
([1, 2, 3, 5, 7, 8, 10], InvertedIndex{Vector{Int64}}([1, 2, 3, 5, 7, 8, 10]))

julia> a
7-element Vector{Int64}:
  1
  2
  3
  5
  7
  8
 10

julia> b
InvertedIndex{Vector{Int64}}([1, 2, 3, 5, 7, 8, 10])

julia> collect(b)
ERROR: MethodError: no method matching length(::InvertedIndex{Vector{Int64}})

The InvertedIndex object itself doesn’t know what it’s the inverse of. As a result, you can use it only as an index into the same-sized array.

I didn’t say this in my original post, but I need to use both idx_l and idx_h independently of the original array, as

for i in idx_h

You can do b = setdiff(eachindex(v), a) if you prefer.
An allocation free way would be b = Iterators.filter(∉(a), eachindex(v))

1 Like

Having now actually read the whole thread (sorry for contributing so irresponsibly before :sweat_smile: )
if you only need the partitioned arrays for iteration, you may prefer not allocating them at all:

function partition_indices(f, v)
    inds = eachindex(v)
    Iterators.filter(i -> f(v[i]), inds), Iterators.filter(i -> !f(v[i]), inds)
end

Technically, you’ll call f twice as many times this way, but that may very well be cheaper than allocating two arrays, depending on your use case.

If you collect the two iterators (not recommended), you will see they are what you want:

julia> v = rand(Bool, 10)'
1×10 adjoint(::Vector{Bool}) with eltype Bool:
 1  0  1  0  1  0  0  0  1  1

julia> collect.(partition_indices(>(0.5), v))
([1, 3, 5, 9, 10], [2, 4, 6, 7, 8])

As a bonus, the type of eachindex doesn’t really matter to you, as per your original question.