# Simple syntax for modifying specific entries of one Array based on indices from another Array?

How would I do this? It seems like there should be some simple syntax for this but if so, I can’t find it.

For example, suppose I have a 10x10 matrix `A`, and a 5x2 matrix `idx`, and the rows of `idx` represent row, column indices into `A`.

``````A = rand(0:9, (10, 10))
indices = [1 1; 2 4; 7 7]
``````

I’d like to perform some operation (in-place, ideally) on those specific indices of `A`. I’ve noticed that I can use comprehensions:

``````[A[i,j] = 42 for (i,j) in eachrow(indices)]
``````

But it feels a little strange to be doing assignment in the comprehension like that (maybe my Python bias is showing), and I also wonder about performance (though that’s not really a significant concern for me for the moment; this is just for a toy problem and for the moment I’m looking more for conciseness/expressiveness).

Is it possible to do something more like a `view` but with an arbitrary set of indices? I.e. something like

``````(@view_at_indices A indices) .= 42
``````

More generally is there a way to combine `view`s so that the combination can be treated identically to a regular `view`? For example, if you have some number of rectangular regions of an image that should all be operated on identically in some fashion.

``````A[CartesianIndex.(Tuple.(eachrow(indices)))] .= 42
``````

You can create views with the same syntax, but `hcat` of views makes a copy of the data. I think it you want to combine views, you are better off combining indices and then creating one view.

3 Likes

Perhaps a little easier:

``````A[CartesianIndex.(eachcol(indices)...)] .= 42
``````

Or, with a view, but not any better I think:

``````B = view(A, CartesianIndex.(eachcol(indices)...))
B .= 42
``````
3 Likes

To complement the helpful answers above: in Julia, it is more natural (and performant) to store those indexes directly in a `Vector` of `CartesianIndex`es.

3 Likes

Agreed.

To answer the question directly: “Simple syntax for modifying specific entries of one Array based on indices from another Array?” The simple syntax for doing this already exists:

``````A[ind] .= 42
``````

It’s just that `ind` has to contain actual indices, linear or cartesian. The `indices` variable that was provided in the OP didn’t actually contain indices, but was just a 2D array of integers, that could be interpreted as indices. But in order to get to the ‘simple syntax’ it is necessary to either make that conversion, or make `indices` have the right type in the first place.

3 Likes

You can also `reinterpret` the rows into `CartesianIndex{2}` (in general, `CartesianIndex{N}` for array dimension `N`)

``````A[reinterpret(CartesianIndex{2}, indices')] .= 1000
``````

To my knowledge, this should be the fastest way to do it.

``````julia> @btime let B = view(\$A, CartesianIndex.(eachcol(\$indices)...))
B .= 42
end;
2.948 μs (10 allocations: 640 bytes)

julia> @btime \$A[CartesianIndex.(Tuple.(eachrow(\$indices)))] .= 42;
1.487 μs (15 allocations: 1008 bytes)

julia> @btime \$A[reinterpret(CartesianIndex{2}, \$indices')] .= 1000
54.819 ns (0 allocations: 0 bytes)
``````
4 Likes