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))
Having now actually read the whole thread (sorry for contributing so irresponsibly before )
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.