julia find in matrix with (row,col) instead of ind

2020-07-14 09:44发布

问题:

In Julia you can find the coordinates of elements in a matrix via:

julia> find( x -> x == 2, [ 1 2 3; 2 3 4; 1 0 2] )
3-element Array{Int64,1}:
 2
 4
 9

These values are correct but I would prefer that I would get the (row,col) tuples instead.

(1,2)
(2,1)
(3,3) 

What is the easiest way to achieve this in Julia?

回答1:

I don't believe there is an inbuilt way to do it, but here is a function to do it

function findmat(f, A::AbstractMatrix)
  m,n = size(A)
  out = (Int,Int)[]
  for i in 1:m, j in 1:n
    f(A[i,j]) && push!(out,(i,j))
  end
  out
end

e.g.

julia> findmat(x->x==2, [ 1 2 3; 2 3 4; 1 0 2] )
3-element Array{(Int64,Int64),1}:
 (1,2)
 (2,1)
 (3,3)

If a large number of items satisfy the condition it might be more efficient to do it in two passes, but I doubt it.



回答2:

In case anyone else finds this you can now use:

ind2sub(a, index)

It returns a tuple of subscripts into array a corresponding to the linear index index



回答3:

The closest thing that I can find in the Julia standard library is findn :

julia> A = [1 2 3; 2 3 4; 1 0 2]
3x3 Array{Int64,2}:
 1  2  3
 2  3  4
 1  0  2

julia> findn(A .== 2)
([2,1,3],[1,2,3])

This gives a tuple of vectors instead of a vector of tuples, though.

Another thing to note is that the match at (2,1) is reported before the one at (1,2). This is because arrays in Julia are stored in column major order, so scanning the array A in storage order will look at the position (2,1) before (1,2).



回答4:

if you wish to avoid defining "new" functions, perhaps:

collect(zip(ind2sub((3,3),find( x -> x == 2, [ 1 2 3; 2 3 4; 1 0 2] ))...))

is what you are looking for. the (3,3) is implicit in the size of the matrix. if the matrix was given by a variable it would look more natural with a size(M)