Reputation: 61
I am trying to create a vector of vectors since I need the data structure to have a fixed number of rows(6) but a variable number of columns. And in each of the units of the data structure, I want to store an instance of a structure. My code is:
struct abc
a::Float64
b::Float64
c
end
k = Vector{Vector{abc}}(6);
for i = 1:6
for j = 1:6
aa, bb, cc = i+1, j+1, rand(3);
instance = abc(aa, bb, cc);
k[i][j] = instance;
end
end
I'm getting this error:
UndefRefError: access to undefined reference
Stacktrace:
[1] getindex(::Array{Array{abc,1},1}, ::Int64) at ./array.jl:549
[2] macro expansion at ./In[7]:5 [inlined]
[3] anonymous at ./:?
Can you guys tell me what I am doing wrong? Thanks!
Upvotes: 3
Views: 1238
Reputation: 10982
The statement:
k = Vector{Vector{abc}}(6);
only initialize the outer Vector with size 6, its components are not even vectors of zero size but simply undefined structs. For example:
julia> x=Vector{Vector{Int}}(4)
4-element Array{Array{Int64,1},1}:
#undef
#undef
#undef
#undef
You can check if a component is assigned/defined (without triggering the error you mentioned in your question) using the isassigned function:
julia> isassigned(x,2) // <---- here
false
julia> x[2]=Vector{Int}(3);
julia> x
4-element Array{Array{Int64,1},1}:
#undef
[140512219699984, 140512277526048, 140512217976944]
#undef
#undef
julia> isassigned(x,2) // <---- here
true
If you know your sizes at construction time, maybe the simplest solution is to use this:
k = [Vector{abc}(5) for i in 1:6]
This will create an (outer) vector of size 6, with all its components being a Vector{abc} of size 5
update: answering your comment.
If you want to define inner vector sizes afterward I would suggest to initialize zero sized vectors then use the resize! function. Code as follows:
struct abc end # empty struct, only for demo
k=[Vector{abc}() for i in 1:6]
for i in 1:length(k)
resize!(k[i],rand(1:6)) # here a random size
for j in 1:length(k[i])
# here do what you want with k[i][j]
end
end
Upvotes: 1
Reputation: 469
Try:
k = fill(Vector{abc}(),6)
for i = 1:6
for j = 1:6
aa, bb, cc = i+1, j+1, rand(3)
instance = abc(aa, bb, cc)
push!(k[i], instance)
end
end
You need to initialize first.
Upvotes: 2
Reputation: 69949
Your variable k
does not have its elements initialized. You can find it when you write:
julia> k
6-element Array{Array{abc,1},1}:
#undef
#undef
#undef
#undef
#undef
#undef
The simplest way to fix it is to use the following pattern:
julia> k = [Vector{abc}(6) for i in 1:6]
6-element Array{Array{abc,1},1}:
abc[#undef, #undef, #undef, #undef, #undef, #undef]
abc[#undef, #undef, #undef, #undef, #undef, #undef]
abc[#undef, #undef, #undef, #undef, #undef, #undef]
abc[#undef, #undef, #undef, #undef, #undef, #undef]
abc[#undef, #undef, #undef, #undef, #undef, #undef]
abc[#undef, #undef, #undef, #undef, #undef, #undef]
And now all works.
Notice that in Julia 0.7/1.0 you have to write k = [Vector{abc}(undef, 6) for i in 1:6]
(with undef
) - exactly to indicate that you are aware that you are creating an array with undefined entries. Similarly Vector{Vector{abc}}(6)
in your original code would fail and you would have to use Vector{Vector{abc}}(undef, 6)
and now, I think, it is more clear that the inner arrays are not initialized.
Finally, you can do both steps in one shot using a comprehension within a comprehension like this:
[[abc(i+1, j+1, rand(3)) for j in 1:6] for i in 1:6]
Upvotes: 1