Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating and assigning values to an array of structs in Julia

Tags:

struct

julia

I would like to define a struct to hold a vector of 3 elements

mutable struct Coords
    r::Array{Float64,3} # essentially holds x,y,z coords
end

I now want to make an array of these structures, and give random values to the vector inside each structure.

This is where I fade out. I have tried a few things which I will describe, but none of them worked.


trial 1:

x = 10                            # I want the array to be of length 10
arrayOfStructs::Array{Coords,x}
for i=1:x
    arrayOfStructs[i].r = rand(3)
end

The error message is

ERROR: LoadError: MethodError: Cannot `convert` an object of type Int64 to an object of type Array{C
oords,10}
Closest candidates are:
  convert(::Type{T<:Array}, ::AbstractArray) where T<:Array at array.jl:489
  convert(::Type{T<:AbstractArray}, ::T<:AbstractArray) where T<:AbstractArray at abstractarray.jl:1
4
  convert(::Type{T<:AbstractArray}, ::LinearAlgebra.Factorization) where T<:AbstractArray at C:\User
s\julia\AppData\Local\Julia-1.0.2\share\julia\stdlib\v1.0\LinearAlgebra\src\factorization.jl:46
  ...
Stacktrace:
 [1] setindex!(::Array{Array{Coords,10},1}, ::Int64, ::Int64) at .\array.jl:769
 [2] getindex(::Type{Array{Coords,10}}, ::Int64) at .\array.jl:366
 [3] top-level scope at C:\Users\Zarathustra\Documents\JuliaScripts\energyTest.jl:68 [inlined]
 [4] top-level scope at .\none:0
in expression starting at C:\Users\Zarathustra\Documents\JuliaScripts\energyTest.jl:67

I don't get why it thinks there are integers involved.

I have tried changing the inside of the for loop to be

arrayOfStructs[i] = Coords(rand(3))

to no avail.

I have also tried initializing arrayOfStructs = []

like image 264
Charlie Crown Avatar asked Jan 17 '19 09:01

Charlie Crown


People also ask

How do I add elements to an array in Julia?

Arrays are mutable type collections in Julia, hence, their values can be modified with the use of certain pre-defined keywords. Julia allows adding new elements in an array with the use of push! command.

How do you fill an array in Julia?

Create an array filled with the value x . For example, fill(1.0, (10,10)) returns a 10x10 array of floats, with each element initialized to 1.0 . If x is an object reference, all elements will refer to the same object. fill(Foo(), dims) will return an array filled with the result of evaluating Foo() once.

How do you create a matrix in Julia?

Julia provides a very simple notation to create matrices. A matrix can be created using the following notation: A = [1 2 3; 4 5 6]. Spaces separate entries in a row and semicolons separate rows. We can also get the size of a matrix using size(A).

How do you create a vector in Julia?

A Vector in Julia can be created with the use of a pre-defined keyword Vector() or by simply writing Vector elements within square brackets([]). There are different ways of creating Vector. vector_name = [value1, value2, value3,..] or vector_name = Vector{Datatype}([value1, value2, value3,..])


1 Answers

N in Array{T,N} defines the dimensionality of the array, that is, an N-dimensional array of type T.

You are not defining an array of size 3 to hold x, y, z coordinates in your struct definition, instead you are defining a 3D Array, which does not suit your purpose.

Yet again, you just declare the type of arrayOfStructs to be a 10-dimensional array without constructing it. You need to define and construct your array properly before using it.

Array types in Julia does not have static size information. Array is a dynamic structure and does not suit your case. For array types with static size information you might want to take a look at StaticArrays.jl.

Here is how I would go with your problem.

mutable struct Coords
    x::Float64
    y::Float64
    z::Float64
end

x = 10 # I want the array to be of length 10
# create an uninitialized 1D array of size `x`
arrayOfStructs = Array{Coords, 1}(undef, x) # or `Vector{Coords}(undef, x)`

# initialize the array elements using default constructor
# `Coords(x, y, z)`
for i = 1:x
    arrayOfStructs[i] = Coords(rand(), rand(), rand())
    # or you can use splatting if you already have values
    # arrayOfStructs[i] = Coords(rand(3)...)
end

You might instead create an empty outer constructor for your type that initializes the fields randomly.

# outer constructor that randomly initializes fields
Coords() = Coords(rand(), rand(), rand())

# initialize the array elements using new constructor
for i = 1:x
    arrayOfStructs[i] = Coords()
end

You may also use comprehensions to easily construct your array.

arrayOfStructs = [Coords() for i in 1:x]

If you still want to use an Array for your field, you may define r as a 1D-array and handle the construction of r in your constructors.

You might want to take a look at the relevant sections in the documentation for Arrays and Composite Types:

https://docs.julialang.org/en/v1/manual/arrays/

https://docs.julialang.org/en/v1/manual/types/#Composite-Types-1

like image 147
hckr Avatar answered Nov 15 '22 09:11

hckr