# Change a vector CartesianIndex

I was wondering if I could get help with this problem.
I have a matrix and find every index where its value is negative.

``````mat = [1 2 3 ; -1 -2 3]

ind = findall(<(0),mat)

2-element Vector{CartesianIndex{2}}:
CartesianIndex(2, 1)
CartesianIndex(2, 2)

``````

Something I want to do is to change the row before each CartesianIndex; CartesianIndex(1,1), CartesianIndex(1,2). I tried to following

``````function ind_ready(;ind = ind)

A = hcat(getindex.(ind,1),getindex.(ind,2))
A[:,1] = A[:,1] .- 1
B = Any[]
C = CartesianIndex[]

for i in 1:length(ind)
B = push!(B,(A[i,1],A[i,2]))
end

for i in 1:length(B)
C = push!(C,CartesianIndex(B[i]))
end

return C

end
``````

Then I get the following

``````2-element Vector{CartesianIndex}:
CartesianIndex(1, 1)
CartesianIndex(1, 2)
``````

However, with this

``````mat[ind_ready()]
``````

returns the following error

``````ArgumentError: unable to check bounds for indices of type CartesianIndex{2}
``````

How can I fix this problem?

Any suggestion would be greatly helpful.

``````ind .= CartesianIndex.(getindex.(ind, 1) .- 1, getindex.(ind, 2))
``````

or equivalently

``````@. ind = CartesianIndex(getindex(ind, 1) - 1, getindex(ind, 2))
``````

which gives

``````julia> mat[ind]
2-element Vector{Int64}:
1
2
``````

Two problems: your `ind_ready()` function actually decrements the second index (with `A[:,2] = A[:,2] .- 1 `), not the first, resulting in invalid `0` indices:

``````julia> i2 = ind_ready()
2-element Vector{CartesianIndex}:
CartesianIndex(2, 0)
CartesianIndex(2, 1)
``````

Second, Julia doesn’t like that your `ind_ready` returns an abstractly typed `CartesianIndex[]` vector and not a concretely typed `CartesianIndex{2}[]` vector:

``````julia> mat[CartesianIndex[CartesianIndex(1,1)]]
ERROR: ArgumentError: unable to check bounds for indices of type CartesianIndex{2}

julia> mat[CartesianIndex{2}[CartesianIndex(1,1)]]
1-element Vector{Int64}:
1
``````

But this error message is confusing and should be fixed: confusing error for array[CartesianIndex[...]] indexing · Issue #48655 · JuliaLang/julia · GitHub

1 Like

You could simply do:

``````ind .-= Ref(CartesianIndex(1,0))
mat[ind]
``````
3 Likes

Oh, right, I forgot that `CartesianIndex` supports vector operations (± and multiplication by scalars).

Thank you very much!

I figured out that my example has the problem you mentioned, so I changed the example to a row. I’ll edit the code in the question accordingly.

I was just wondering one more thing. Is there a way that I can put conditions? I want to reduce by one if the cartesian index is bigger than one?

Thank you so much. Now I can cut my messy codes into half Yes, of course. One solution would be to include a call to `max` (or `ifelse` or similar):

``````ind .= CartesianIndex.(max.(1, getindex.(ind, 1) .- 1), getindex.(ind, 2))
``````

but when things become sufficiently complicated at some point it becomes clearer to write an “scalar” expression that does what you want, and either broadcast it or use a comprehension or `map`. For example, one of:

``````newind = map!(ind) do c
CartesianIndex(max(1, c), c)
end

map!(ind, ind) do c
CartesianIndex(max(1, c), c)
end

newind = [CartesianIndex(max(1, c), c) for c in ind]

f(c) = CartesianIndex(max(1, c), c)
ind .= f.(c)

ind .= (c -> CartesianIndex(max(1, c), c)).(ind)
``````

and of course once you write it like this you can use `if` statements or whatever you want to transform `c`.

1 Like

If your need is to handle cases where some negative value is in the first row, you could make use of a variant of @rafael.guerra solution

``````
mat3 = [-2 -3 4; 1 2 3 ; -1 -2 3]

ind3 = findall(<(0),mat3)

ind3 .-= Ref(CartesianIndex(1,0))

nind=[i - CartesianIndex(1,0) for i in ind3 if i.I > 1]
``````
1 Like

I thank all of you so much !