Zoom Arrays

Last updated: January 12, 2023

 Table of contents

Arrays are mutable and indexable collections of elements.

Vectors

Unidimensional arrays in Julia are called vectors.

Vectors of one element

[3]
1-element Vector{Int64}:
 3
[3.4]
1-element Vector{Float64}:
 3.4
["Hello, World!"]
1-element Vector{String}:
 "Hello, World!"

Vectors of multiple elements

[3, 4]
2-element Vector{Int64}:
 3
 4

Two dimensional arrays

[3 4]
1ร—2 Matrix{Int64}:
 3  4
[[1, 3] [1, 2]]
2ร—2 Matrix{Int64}:
 1  1
 3  2

Syntax subtleties

These 3 syntaxes are equivalent:

[2 4 8]
1ร—3 Matrix{Int64}:
 2  4  8
hcat(2, 4, 8)
1ร—3 Matrix{Int64}:
 2  4  8
cat(2, 4, 8, dims=2)
1ร—3 Matrix{Int64}:
 2  4  8

These 4 syntaxes are equivalent:

[2
 4
 8]
3-element Vector{Int64}:
 2
 4
 8
[2; 4; 8]
3-element Vector{Int64}:
 2
 4
 8
vcat(2, 4, 8)
3-element Vector{Int64}:
 2
 4
 8
cat(2, 4, 8, dims=1)
3-element Vector{Int64}:
 2
 4
 8

Elements separated by semi-colons or end of lines get expanded vertically.
Those separated by commas do not get expanded.
Elements separated by spaces or tabs get expanded horizontally.

Compare the outputs of the following:
[1:2; 3:4]
4-element Vector{Int64}:
 1
 2
 3
 4
[1:2
 3:4]
4-element Vector{Int64}:
 1
 2
 3
 4
[1:2, 3:4]
2-element Vector{UnitRange{Int64}}:
 1:2
 3:4
[1:2 3:4]
2ร—2 Matrix{Int64}:
 1  3
 2  4

Arrays and types

In Julia, arrays can be heterogeneous:

[3, "hello"]
2-element Vector{Any}:
 3
  "hello"

This is possible because all elements of an array, no matter of what types, will always sit below the Any type in the type hierarchy.

Initializing arrays

Below are examples of some of the functions initializing arrays:

rand(2, 3, 4)
2ร—3ร—4 Array{Float64, 3}:
[:, :, 1] =
 0.287968  0.460719  0.153366
 0.280913  0.539013  0.00871208

[:, :, 2] =
 0.265209  0.655567  0.537502
 0.26706   0.674964  0.861944

[:, :, 3] =
 0.953564  0.907631   0.828447
 0.515199  0.0105021  0.695217

[:, :, 4] =
 0.583481  0.84174    0.970322
 0.152088  0.0482478  0.560455
rand(Int64, 2, 3, 4)
2ร—3ร—4 Array{Int64, 3}:
[:, :, 1] =
 283631121498974884  5523893714833594940  -766547241876310447
 193907474732102996   117640300918070571  2207880073658713015

[:, :, 2] =
 5448671591094212079  -6818252937298802646  -6593535695756447601
 5644809475266060301  -8052566091470393472   -894025445933767430

[:, :, 3] =
 -4704833441856952965  -7395983219772785088   7078606437917951545
 -3634511620742085399  -2898846961850744754  -5207663753325904582

[:, :, 4] =
 -3498469619188751973  8296251293241855904  9094565288786527968
  -825154316697021437  6105724017006134850  3820314553677873025
zeros(Int64, 2, 5)
2ร—5 Matrix{Int64}:
 0  0  0  0  0
 0  0  0  0  0
ones(2, 5)
2ร—5 Matrix{Float64}:
 1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0
reshape([1, 2, 4, 2], (2, 2))
2ร—2 Matrix{Int64}:
 1  4
 2  2
fill("test", (2, 2))
2ร—2 Matrix{String}:
 "test"  "test"
 "test"  "test"

Indexing

As in other mathematically oriented languages such as R, Julia starts indexing at 1.

Indexing is done with square brackets:

a = [1 2; 3 4]
2ร—2 Matrix{Int64}:
 1  2
 3  4
a[1, 1]
1
a[1, :]
2-element Vector{Int64}:
 1
 2
a[:, 1]
2-element Vector{Int64}:
 1
 3
Index the element on the 3rd row and 2nd column of b :
b = ["wrong" "wrong" "wrong"; "wrong" "wrong" "wrong"; "wrong" "you got it" "wrong"]
3ร—3 Matrix{String}:
 "wrong"  "wrong"       "wrong"
 "wrong"  "wrong"       "wrong"
 "wrong"  "you got it"  "wrong"

As in Python, by default, arrays are passed by sharing:

a = [1, 2, 3];
a[1] = 0;
a
3-element Vector{Int64}:
 0
 2
 3

This prevents the unwanted copying of arrays.

Broadcasting

To apply a function to each element of a collection rather than to the collection as a whole, Julia uses broadcasting.

a = [-3, 2, -5]
3-element Vector{Int64}:
 -3
  2
 -5
abs(a)
LoadError: MethodError: no method matching abs(::Vector{Int64})
Closest candidates are:
  abs(::Unsigned) at /usr/share/julia/base/int.jl:179
  abs(::Signed) at /usr/share/julia/base/int.jl:180
  abs(::Complex) at /usr/share/julia/base/complex.jl:277
  ...

This doesn’t work because the function abs only applies to single elements.

By broadcasting abs, you apply it to each element of a:

broadcast(abs, a)
3-element Vector{Int64}:
 3
 2
 5

The dot notation is equivalent:

abs.(a)
3-element Vector{Int64}:
 3
 2
 5

It can also be applied to the pipe, to unary and binary operators, etc.

a .|> abs
3-element Vector{Int64}:
 3
 2
 5
Try to understand the difference between the following 2 expressions:
abs.(a) == a .|> abs
true
abs.(a) .== a .|> abs
3-element BitVector:
 1
 1
 1
Hint: 0/1 are a short-form notations for false/true in arrays of booleans.

Comprehensions

Julia has an array comprehension syntax similar to Python’s:

[ 3i + j for i=1:10, j=3 ]
10-element Vector{Int64}:
  6
  9
 12
 15
 18
 21
 24
 27
 30
 33

Comments & questions