How to convert a Matrix{Array{Int64, 0}} to a Matrix{Int64}

A function returns a matrix nr, like this:

3×3 Matrix{Array{Int64, 0}}:
 fill(4)  fill(2)  fill(1)
 fill(1)  fill(2)  fill(2)
 fill(2)  fill(1)  fill(1)

fill(4)[] is displayed as 4.
How to get from the matrix nr the matrix:

[ 4 2 1;
  1 2 2;
  2 1 1]

in a more compact way than:

Nr= reshape([nr[i][] for i in eachindex(nr)], 3,3)

Does this work for you?

julia> a = [ Ref(1)  Ref(2)
             Ref(3)  Ref(4) ]
2×2 Matrix{Base.RefValue{Int64}}:
 RefValue{Int64}(1)  RefValue{Int64}(2)
 RefValue{Int64}(3)  RefValue{Int64}(4)

julia> getfield.(a,1)
2×2 Matrix{Int64}:
 1  2
 3  4

(I’m not sure how to build your example)

  1. In any case, you can map over your array to avoid explicit reshaping:
    julia> A0 = reshape([fill(i) for i = 1:4], 2, 2)
    2×2 Matrix{Array{Int64, 0}}:
    fill(1)  fill(3)
    fill(2)  fill(4)
    
    julia> map(x -> x[], A0)
    2×2 Matrix{Int64}:
    1  3
    2  4
    
  2. fill(4) is indeed a zero-dimensional array, i.e., typeof(fill(4)) == Array{Int64, 0} and can be accessed as fill(4)[], i.e., without giving any index. The corresponding functional form is getindex(fill(4)) which can be broadcasted:
    julia> getindex.(A0)
    2×2 Matrix{Int64}:
    1  3
    2  4
    
1 Like
julia> a = [fill(a+b) for a in 1:3, b in 1:3]
3×3 Matrix{Array{Int64, 0}}:
 fill(2)  fill(3)  fill(4)
 fill(3)  fill(4)  fill(5)
 fill(4)  fill(5)  fill(6)

julia> only.(a)
3×3 Matrix{Int64}:
 2  3  4
 3  4  5
 4  5  6

only(x) is the same as x[] which is the same as getindex(x) I believe

7 Likes

Great, thank you!!!

In this case yes, i.e., @less only(fill(4)) shows that

# @ Base.Iterators iterators.jl:1534
only(a::AbstractArray{<:Any, 0}) = @inbounds return a[]

(A more basic question is why your function is returning an array of 0-dimensional arrays. That sounds like it could be a usage mistake that you might want to correct, rather than fixing up the output.)

3 Likes

I would use stack(array) or only.(array). But I’ll echo others’ thoughts that perhaps one could avoid creating this unusual matrix representation in the first place…

That odd array is returned by this code:

import Polynomials: Polynomial, derivative
import StatsBase: sample

function nroots!(p, z;eps=1e-05, maxiter=50)
   dp= derivative(p)
   ddp=derivative(dp)
   prod=ddp*p 
   nr=zeros(Int, size(z)) 
   for _ in 1:maxiter 
       z, zprev=  z-p(z)/(dp(z) - prod(z)/(2*dp(z))), z
       nr[findall(x->x^2>eps, abs(z-zprev))] .+= 1
   end 
   return nr 
end 
x= 0:0.05:1
z= x' .+ x*im
p = Polynomial(sample([1.0, -1.0, 1im, -1im], 5))
nr=nroots!.(p, z)
1 Like

Side note, is this a bug? Why in the matrix case the return is an Int matrix? (with a generator it is not)

julia> a = [ fill(1), fill(2) ]
2-element Vector{Array{Int64, 0}}:
 fill(1)
 fill(2)

julia> a = [ fill(1) fill(2) ]
1×2 Matrix{Int64}:
 1  2

Don’t think that is a bug, but the same as observed here, i.e., [x, y] lowers to vect(x, y) whereas [x y] lowers to hcat(x, y).

2 Likes

For completeness this is the corresponding vector concatenation:

julia> a = [ fill(1); fill(2) ]
2-element Vector{Int64}:
 1
 2

There is no higher-dimensional non-concatenating constructor, but to some extent it can be worked around by wrapping the elements in one-element containers and concatenate those, e.g. the highly contrived

julia> a = [ fill(fill(1)) fill(fill(2)) ]
1×2 Matrix{Array{Int64, 0}}:
 fill(1)  fill(2)
1 Like