Julia Language: How to create an array of structs inside a for loop

Viewed 450

here in this code, I am trying to create an array of struct called Linestruct

but I am getting this error "bound error, attempts to access0-element array..."

using CSV
df=CSV.read("F:/B/Mayar/lineData.CSV")

struct Linestruct
    buses::Vector{Int}
    res::Float64
    ind::Float64
    imp_mag::Float64
    imp_angle::Float64
    p::Float64
    q::Float64
    state::String
end
CREATE_Linestruct() = Linestruct([0,0], 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, "overloaded")
Linestruct(buses_line, res_line, ind_line) = Linestruct(buses_line, res_line,
    ind_line, 0.0, 0.0, 0.0, 0.0, "overloaded")

l2 = Linestruct([1,2,3], 0.0, 0.0)
l3=CREATE_Linestruct()
number_lines=size(df,1)
array_lines=Array{Linestruct,1}()

for x in 1:N
l4=CREATE_Linestruct()
array_lines[x]=l4


end
2 Answers

The issue is that the line

array_lines=Array{Linestruct,1}()

creates an empty array (i.e an array of size 0).

Afterwards, the line

array_lines[x]=l4

does not make the aray grow (unlike what would happen in a language like Matlab): it tries to change the value at index x in the array. Since the array is empty, you get an error.


A minimal example reproducing this situation might be (note that I'm using a vector of Int values here, since your problem is not really related to the array storing structs rather than native types):

julia> a = Array{Int, 1}()
0-element Array{Int64,1}

julia> a[1] = 1
ERROR: BoundsError: attempt to access 0-element Array{Int64,1} at index [1]

A way to fix this could be to make the array grow using push! to insert new values at the end of it:

julia> for i in 1:3
           push!(a, i)
       end

julia> a
3-element Array{Int64,1}:
 1
 2
 3

Let's consider this simple struct:

struct Mine
    a::Int
    b::String
end

Vectorization is the most concise form - usually when creating Arrays of structs I try to avoid loops:

julia> a = Mine.([1,2,3],["b1","b2","b3"])
3-element Array{Mine,1}:
 Mine(1, "b1")
 Mine(2, "b2")
 Mine(3, "b3")

Comprehension is also nice:

julia> [Mine(a,b) for (a,b) in [(1,"b1"),(2,"b2"),(3,"b3") ]]
3-element Array{Mine,1}:
 Mine(1, "b1")
 Mine(2, "b2")
 Mine(3, "b3")

If there is no other way create an empty Array and push! or append! elements to it:

julia> ar = Mine[]
0-element Array{Mine,1}

julia> push!(ar, Mine(1,"a1"));

julia> append!(ar, [Mine(2,"b1"),Mine(3,"b3")])
3-element Array{Mine,1}:
 Mine(1, "a1")
 Mine(2, "b1")
 Mine(3, "b3")
Related