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.
I have the same question and found this topic, and I found the answer in the Julia document. The answer to this topic is not very precise.
The official document answers your question in detail: Single- and multi-dimensional Arrays ¡ The Julia Language
For âstandard arraysâ and âstandard indicesâ
In the expression
A[I_1, I_2, ..., I_n]
, eachI_k
may be a scalar index, an array of scalar indices, or an object that represents an array of scalar indices and can be converted to such byto_indices
:
- A scalar index. By default this includes:
- Non-boolean integers
CartesianIndex{N}
s, which behave like anN
-tuple of integers spanning multiple dimensions (see below for more details)
You cannot use Boolean as the index.
Thatâs because my initial question wasnât formulated well. Through this discussion, I learned that
- my real question was How to find out the type of the index of the given array? and
- the answer was/is
keytype(v)
.
This was a better way to pose my question because you get a better solution to the same problem:
function partition_vals(vals, thresh)
idx_l = Vector{keytype(vals)}()
idx_h = Vector{keytype(vals)}()
for i in eachindex(vals)
(vals[i] < thresh) ? push!(idx_l, i) : push!(idx_h, i)
end
(idx_l, idx_h)
end
Why is it better than Vector{Int}()
? Because the above function works not only with Vectors but also with Dicts (and anything that implements indexing [ ]
).
Agreeing that a generic solution is better whenever possible. Seems that your function still has a bug though:
julia> A = [1 2; 3 4];
julia> partition_vals(A, 3)`
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type CartesianIndex{2}
The reason being â as alluded to above â that keytype
does not necessarily match the type of eachindex
. So, a proper generic version of your function could either use
eltype(eachindex(vals))
together with iterating overi in eachindex(vals)
- or
keytype(vals)
together with iterating overi in keys(vals)
.
Both should work for vectors, dicts and arrays. For the latter, the meaning of indices is slightly different though as a multi-dimensional array can be accessed either by a linear index, i.e., as provided by eachindex
, or a multi-dimensional index, e.g., a CartesianIndex
. Here is a small example:
julia> A[1, 2] # multi-dimensional index
2
julia> A[CartesianIndex(1, 2)] # same as above
2
julia> A[3] # linear index
2
julia> eachindex(A) # gives linear indices
Base.OneTo(4)
julia> eltype(eachindex(A)) # type of linear indices, i.e., like typeof(first(eachindex(A)), but works for empty vectors
Int64
julia> keys(A) # gives multi-dimensional indices
CartesianIndices((2, 2))
julia> keytype(A) # type of keys
CartesianIndex{2}