Initializing Arrays and Matrices

by Martin D. Maas, Ph.D

Initialize empty multidimensional arrays of various types.

Direct Input

The most convenient way to input a matrix is by using whitespace-separated columns, and semicolons for rows, as follows:

A = [1 2 3; 1 2 4; 2 2 2]     # 3×3 Matrix{Float64}

For easier readability, you can also resort to newlines:

A = [1 2 3; 
     1 2 4; 
     2 2 2]     

As for inputting vectors, each element can be separated by either commas or semicolons. However, note that separating entries with whitespace will result in a 1x3 matrix, which is a different type of entity for Julia than a vector.

b1 = [4.0, 5, 6]                # 3-element Vector{Float64}
b2 = [4.0; 5; 6]                # 3-element Vector{Float64}
m1 = [4.0 5 6]                  # 1×3 Matrix{Float64}

Julia also supports arrays of non-numerical types such as Strings, or even arrays of Any, which could include strings and numbers, and can be initialized as:

A = ["Hello", 1, 2, 3]
  4-element Vector{Any}:

Array Comprehensions

A very concise way to initialize and array is by resorting to so-called array comprehensions.

The following code builds an array with the first 100,000 terms of a quadratic series, and then performs the sum.

v = [1/n^2 for n=1:100000]
x = sum(v)

When using parenthesis instead of the square brackets, Julia will produce a slightly different object: a generator. Generators can be iterated to produce the required values when needed.

As the underlying array isn’t allocated in memory in advance, the generator could have better performance than the array comprehension.

gen = (1/n^2 for n=1:100000)
x = sum(gen)

Undefined (undef) Arrays

Array in Julia can be constructed in various ways, other than direct initialization of arrays from given values.

For examples, for performance reasons, it is wise to initialize arrays of a given type (and size), without specifying any values. That is, not even initializing a new array with zeros.

To do this, we can employ keywords such as Vector{T}, Matrix{T} or Array{T}, where T is a type (see, for example, Numeric Types in the documentation). Among numeric types, arguably Float64 (double-precision real), ComplexF64 (double-precision complex), and Int64 are among the most frequently used in numerical computing.

The reason to declare undefined arrays is to be able to fill them later — for example, with the use of a for loop.

What happens under the hood when we declare an undef array, is that a certain portion of memory gets reserved (or allocated) for this specific use. As the computer is not even filling that chunk of memory with zeros, we are saving some time.

The following are some examples of undef arrays of type Float64:

n = 5
A1 = Array{Float64}(undef,n,n)          # 5×5 Matrix{Float64}
A2 = Matrix{Float64}(undef,n,n)         # 5×5 Matrix{Float64}

V1 = Array{Float64}(undef,n)            # 5-element Vector{Float64}
V2 = Vector{Float64}(undef,n)           # 5-element Vector{Float64}

For non-numerical types like String or Any, we can resort to

A = Array{String}(undef,n)
A = Array{Any}(undef,n)

Empty Arrays

Empty arrays can be a useful starting point when we are in a situation where it is hard or impossible to know which array sizes we need in advance. An empty array can be later grown dynamically, and filled with values. (see the “Dynamic Arrays” section below in this page).

To initialize an empty array, it is perfectly valid to use n = 0 in the above expressions.

v = Array{Float64}(undef,0)

There is a shorthand for this expression:

v = Float64[]

A possible source of errors would be to confuse this array with an empty array of “Any” type, which is initialized as follows:

v = []    # Same as Any[], and you can't change this type easily later (gotcha!)

If we later fill this array dynamically with Float values, its type would remain fixed at “Any”, which could lead to bad performance — or even errors, if we plan on passing this array to a function which requires arrays of type Float, for example.

Initializing Special Kind of Arrays

Julia provides many functions for constructing and initializing special kinds of arrays. For example, for null matrices we can use the zeros function, and for matrices filled with ones we have the ones function.

A = zeros(8,9)
B = ones(8,9)

The documentation includes many other examples, such as matrices with different types of random entries, boolean values, and so forth, such as:

C = rand(6,6)

In the case of the identity matrix, placing an integer right before a letter ‘I’ will do the job, but this requires the LinearAlgebra package:

using LinearAlgebra
M = 5I + rand(2,2)

 2×2 Matrix{Float64}:
 5.50162   0.462804
 0.498287  5.30439