# How to query elements in a matrix diagonal to a given point

I’m wondering if there’s an efficient way to return all of the elements in a matrix that are diagonal to some starting point. For example, given the following matrix:

``````julia> A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]
4×4 Array{Int64,2}:
1   2   3   4
5   6   7   8
9  10  11  12
13  14  15  16
``````

If I want to query the matrix to return all elements that are diagonal to the number 7 (so `A[2,3]`), I should get back `[2, 12, 4, 10, 13]`. If I query the matrix at point `A[4,4]` (where 16 is), I would want to get back `[1,6,11]`.

Is there a package that already does something like this or is this going to take a custom function?

EDIT: The matrices that I need this for will always be square

How about `Diagonal(A)`? You will need to put `using LinearAlgebra` first to bring in the package. In general, you might want to read https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/index.html

Hi Oscar. So it looks like this simply converts my matrix into a `Diagonal` matrix, keeping only the main diagonal. Am I missing something here? Can I use this to get all elements that are diagonal and anti-diagonal to some specific point?

I think you are definitely going to need to write your own function for that.

1 Like

I think you are definitely going to need to write your own function for that.

This won’t be happening at this hour on a Sunday night I’ll take a crack at it tomorrow and if I come up with something decent I’ll post here

Does this work? It’s not optimized, but should be decent

``````function diagonals(A::Matrix{T},i,j) where T
s = size(A)
out = Vector{T}()
for row in 1:s[1]
if i == row
continue
end
col1 = j - (i-row)
if 1 <= col1 <= s[2]
append!(out, A[row,col1])
end
col2 = j + (i-row)
if 1 <= col2 <= s[2]
append!(out, A[row,col2])
end
end
return out
end``````
2 Likes

Might make sense to exploit the strideness:

``````julia> function diagonals(A, i, j)
n = size(A,1)
s = (j-1)*n + i
[A[s-(n+1):-(n+1):begin]; A[s+(n+1):(n+1):end]; A[s+(n-1):(n-1):end-1]; A[s-(n-1):-(n-1):begin+1]]
end
diagonals (generic function with 1 method)

julia> diagonals(A, 2,3)
5-element Array{Int64,1}:
2
12
4
10
13
``````

Though the code still needs to be fixed for edge cases:

``````julia> diagonals(A,4,4) # this is wrong
7-element Array{Int64,1}:
11
6
1
4
7
10
13
``````
2 Likes

Alright, here’s what I came up with. It performs horrendously compared to either of the solutions posted by @Oscar_Smith and @dlfivefifty and it deviates a bit from the stated objective as it returns two different vectors, both of which include the element at the query starting point. About the only thing that it has going for it is that it’s a one-liner:

``````diagonals(A, i, j) = diag(A,j-i), diag(reverse(A,dims=1),(i+j)-(size(A,1)+1))

julia> A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]
4×4 Array{Int64,2}:
1   2   3   4
5   6   7   8
9  10  11  12
13  14  15  16

julia> diagonals(A,3,4)
([2, 7, 12], [15, 12])

julia> diagonals(A,2,2)
([1, 6, 11, 16], [9, 6, 3])
``````
1 Like