Slicing and boolean indexing in multidimensional arrays

I’m curious why the following 3D array slicing works for the i index but not for the j index:

``````T = Array(reshape(1:2*3*4, 2,3,4))
i = zeros(Bool, 2,3)
i[1,2:3] .= 1
display(T[i,:])
j = zeros(Bool, 3,4)
j[1,2:3] .= 1
display(T[:,j])
``````

when the seemingly-analogous operation on a 2D array works either way:

``````M = Array(reshape(1:4*5, 4,5))
k = zeros(Bool, 4)
k[2:3] .= 1
display(M[k,:])
l = zeros(Bool, 5)
l[2:3] .= 1
display(M[:,l])
``````

I’m interested in both why it doesn’t work, and any suggestions for a reasonably-elegant work-around.

2 Likes

I have no idea why it does not work but a “reasonably elegant workaround” might be:

``````jj = findall(j)
T[:,jj]
``````
2 Likes

This should be a bug in `Base.to_indices`, more specific

``````@inline to_indices(A, inds, I::Tuple{Union{Array{Bool,N}, BitArray{N}}}) where {N} =
(_maybe_linear_logical_index(IndexStyle(A), A, I[1]),)
``````

It should be something like

``````@inline to_indices(A, inds, I::Tuple{Union{Array{Bool,N}, BitArray{N}}}) where {N} =
ndims(A) == N ? (_maybe_linear_logical_index(IndexStyle(A), A, I[1]),) : (to_index(A, I[1]),)
``````

Thanks, this does meet my needs for a workaround at the moment.

This seems very relevant, but I don’t fully understand it. Could you elaborate a bit on how your proposed update works? Are you planning to submit a bug-report about this?

1 Like

On master, if `IndexStyle(A) === IndexLinear()`, `Base.to_indices` always transforms the last logical index into `Base.LogicalIndex{Int}`. Thus `T[:,j]` behaves as `T[:,findall(vec(j))]`, which is always not correct.
The above change avoids the wrong optimization by adding a dimension check. I’ve open a PR to fix this.