Introducing Julia/Arrays and tuples
Contents
 1 Storage: Arrays and Tuples
 2 Arrays
 3 Creating arrays
 3.1 Creating simple arrays
 3.2 Creating 2D arrays and matrices
 3.3 Creating arrays using range objects
 3.4 More range objects
 3.5 Collecting up the values in a range
 3.6 Using comprehensions and generators to create arrays
 3.7 Creating and filling an array
 3.8 Array constructor
 3.9 Copying arrays
 3.10 Matrix operations: using arrays as matrices
 4 Accessing the contents
 5 Modifying array contents: adding and removing elements
 5.1 Removing elements
 5.2 Other functions
 5.3 Setting the contents of arrays
 5.4 Passing arrays to functions
 5.5 Matrix arithmetic
 5.6 Joining arrays and matrices
 5.7 Growing or extending arrays
 5.8 Manipulating matrices
 5.9 Applying functions to matrices
 5.10 Matrix norms
 5.11 Scaling and rotating matrices
 5.12 Sorting arrays
 6 Tuples
Storage: Arrays and Tuples[edit]
In Julia, groups of related items are usually stored in arrays, tuples, or dictionaries. Arrays can be used for storing vectors and matrices. This section concentrates on arrays and tuples; for more on dictionaries, see Dictionaries and Sets.
Arrays[edit]
An array is an ordered collection of elements. It's often indicated with square brackets and commaseparated items. You can create arrays that are full or empty, and arrays that hold values of different types or restricted to values of a specific type.
In Julia, arrays are used for lists, vectors, tables, and matrices.
A onedimensional array acts as a vector or list. A 2D array can be used as a table or matrix. And 3D and moreD arrays are similarly thought of as multidimensional matrices.
Creating arrays[edit]
Creating simple arrays[edit]
Here's how to create a simple onedimensional array:
julia> a = [1, 2, 3, 4, 5] 5element Array{Int64,1}: 1 2 3 4 5
Julia informs you ("5element Array{Int64,1}") that you've created a 1dimensional array with 5 elements, each of which is a 64bit integer, and bound the variable a
to it. Notice that intelligence is applied to the process: if one of the elements looks like a floatingpoint number, for example, you'll get an array of Float64s:
julia> a1 = [1, 2, 3.0, 4, 5] 5element Array{Float64,1}: 1.0 2.0 3.0 4.0 5.0
Similarly for strings:
julia> s = ["this", "is", "an", "array", "of", "strings"] 6element Array{String,1}: "this" "is" "an" "array" "of" "strings"
returns an array of strings, and:
julia> trigfuns = [sin, cos, tan] 3element Array{Function,1}: sin cos tan
returns an array of Julia functions.
You can specify the type and the dimensions of an array with the Array()
function (notice that uppercase "A"), putting the type in curly braces:
julia> array = Array{Int64}(5) 5element Array{Int64,1}: 4516561312 4516561376 4516561440 408021893238 4294967362
julia> array3 = Array{Int64}(2,2,2) 2x2x2 Array{Int64,3}: [:, :, 1] = 0 0 0 0 [:, :, 2] = 0 0 0 0
Sometimes you'll see the new array filled with randomlooking numbers:
julia> array = Array{Int64}(5) 5element Array{Int64,1}: 2322280078457970723 3256719550777995314 3904966330563964977 744304806301413434 0 julia> array[1] 2322280078457970723
which is a reminder that you've created an uninitialized array but haven't filled it with any sensible information.
It's possible to create arrays with elements of different types:
julia> [1, "2", 3.0, sin, pi] 5element Array{Any, 1}: 1 "2" 3.0 sin π = 3.1415926535897...
Here, the array has five elements, but they're an odd mixture: numbers, strings, functions, constants — so Julia creates an array of type Any:
julia> typeof(ans) Array{Any,1}
To create an array of a specific type, you can use the type definition and square brackets:
julia> Int64[1, 2, 3, 4] 4element Array{Int64,1}: 1 2 3 4
If you think you can fool Julia by sneaking in a value of the wrong type while declaring a typed array, you'll be caught out:
julia> Int64[1, 2, 3, 4, 5, 6, 7, 8, 9, 10.1] ERROR: InexactError()
You can create empty arrays this way too:
julia> b = Int64[] 0element Array{Int64,1}
julia> b = String[] 0element Array{String,1}
julia> b = Float64[] 0element Array{Float64,1}
Creating 2D arrays and matrices[edit]
If you leave out the commas when defining an array, you can create 2D arrays quickly. Here's a single row, multicolumn array:
julia> [1 2 3 4] 1x4 Array{Int64,2}: 1 2 3 4
Notice the ,2}
in the first row of the response.
You can use a semicolon to add another row:
julia> [1 2 3 4 ; 5 6 7 8] 2x4 Array{Int64,2}: 1 2 3 4 5 6 7 8
Row and column vectors[edit]
Compare these two: [1,2,3,4,5]
and [1 2 3 4 5]
.
With the commas, this array could be called a "column vector", with 5 rows and 1 column:
julia> [1, 2, 3, 4, 5] 5element Array{Int64,1}: 1 2 3 4 5
But with the spaces, this array could be called a "row vector", with 1 row and 5 columns:
julia> [1 2 3 4 5] 1x5 Array{Int64,2}: 1 2 3 4 5
 notice the {Int64,2}
here, which tells you that this is a 2D array of Int64s (with 1 row and 5 columns). In both cases, they're standard Julia arrays.
Arrays created like this can be used as matrices:
julia> [1 2 3; 4 5 6] 2x3 Array{Int64,2}: 1 2 3 4 5 6
And of course you can create arrays/matrices with 3 or more dimensions.
There are a number of functions which let you create and fill an array in one go. See Creating and filling an array.
Notice how Julia distinguishes between Array{Float64,1}
and Array{Float64,2}
:
julia> x = rand(5) 5element Array{Float64,1}: 0.183247 0.480208 0.623144 0.342792 0.0400695
julia> x = rand(5, 1) 5x1 Array{Float64,2}: 0.553224 0.0061835 0.762059 0.643796 0.655135
Julia provides the Vector
and Matrix
constructor functions, but these are simply aliases for one and two dimensional arrays:
julia> Vector(5) 5element Array{Any,1}: #undef #undef #undef #undef #undef julia> Matrix(5, 5) 5x5 Array{Any,2}: #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef #undef
Creating arrays using range objects[edit]
In Julia, the colon (:
) has a number of uses. One use is to define ranges and sequences of numbers. You can create a range object by typing it directly:
julia> 1:20 1:20
Or you can use the range()
function to make a range object:
julia> range(1, 10) 1:10
It may not look very useful in that form, but it provides the raw material for any job in Julia that needs a range or sequence of numbers.
You can use it in a loop expression:
julia> for n in 1:10 print(n) end 12345678910
Or you can use collect()
to build an array consisting of those numbers:
julia> collect(1:10) 10element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10
You don't have to start and finish on an integer either:
julia> collect(3.5:9.5) 7element Array{Float64,1}: 3.5 4.5 5.5 6.5 7.5 8.5 9.5
There's also a threepiece version of a range object, start:step:stop, which lets you specify a step size other than 1. For example, this builds an array with elements that go from 0 to 100 in steps of 10:
julia> collect(0:10:100) 11element Array{Int64,1}: 0 10 20 30 40 50 60 70 80 90 100
To go down instead of up, you have to use a negative step value:
julia> collect(4:1:1) 4element Array{Int64,1}: 4 3 2 1
Instead of using collect()
to create an array from the range, you could use the ellipsis (...
) operator (three periods) after the last element:
julia> [1:6...] 6element Array{Int64,1}: 1 2 3 4 5 6
(The ...
ellipsis is sometimes called the splat operator. It represents a sequence of arguments.)
However, collect()
is faster and the recommended method of converting ranges to arrays. But you can use range objects in many situations in Julia, and you don't always need to expand them into arrays.
More range objects[edit]
Another useful function is linspace()
, which constructs a range object that goes from a start value to an end value taking a specific number of steps. You don't have to calculate the increment, because Julia calculates the step size for you. For example, to go from 1 to 100 in exactly 12 steps:
julia> linspace(1, 100, 12) 1.0:9.0:100.0
You can use this range object to build an array:
julia> collect(linspace(1, 100, 12)) 12element Array{Float64,1}: 1.0 10.0 19.0 28.0 37.0 46.0 55.0 64.0 73.0 82.0 91.0 100.0
Notice that it provided you with a Float64 array, rather than an Integer array, even though the values could have been integers.
There's a logarithmic version called logspace()
, here going from 10^{1} to 10^{2} in five steps:
julia> logspace(1, 2, 5) 5element Array{Float64,1}: 10.0 17.7828 31.6228 56.2341 100.0
Use step()
on a range object to find out what the step size is:
julia> step(linspace(1, 100, 12)) 9.0
You can also use range()
if you know the start and step, but not the end, and you know how many elements you want:
julia> collect(range(1, 3, 20)) 20element Array{Int64,1}: 1 4 7 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58
Collecting up the values in a range[edit]
As you've seen, if you're not using your range object in a for
loop, you can use collect()
to obtain all the values from a range object directly:
julia> collect(0:5:100) 21element Array{Int64,1}: 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
It's worth remembering that you often won't need to convert ranges to arrays before working on them — you can usually iterate over things directly. For example, you don't have to write this:
julia> for i in collect(1:6) println(i) end 1 2 3 4 5 6
because it works just as well without the collect()
:
julia> for i in 1:6 println(i) end 1 2 3 4 5 6
Using comprehensions and generators to create arrays[edit]
A useful way to create arrays where each element can be produced using a small computation is to use comprehensions (described in Comprehensions).
For example, to create an array of 5 numbers:
julia> [n^2 for n in 1:5] 5element Array{Int64,1}: 1 4 9 16 25
With two iterators, you can easily create a 2D array or matrix:
julia> [r * c for r in 1:5, c in 1:5] 5x5 Array{Int64,2}: 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25
You can add an if
test at the end to filter (keep) values that pass a test:
julia> [i^2 for i=1:10 if i != 5] 9element Array{Int64,1}: 1 4 9 16 36 49 64 81 100
Generator expressions are similar, and can be used in a similar way:
julia> collect(x^2 for x in 1:10) 10element Array{Int64,1}: 1 4 9 16 25 36 49 64 81 100
julia> collect(x^2 for x in 1:10 if x != 1) 9element Array{Int64,1}: 4 9 16 25 36 49 64 81 100
The advantage of generator expressions is that they generate values when needed, rather than build an array to hold them first.
Creating and filling an array[edit]
There are a number of functions that let you create arrays with specific contents. These can be very useful when you're using 2D arrays as matrices:
 zeros(m, n)
creates an array/matrix of zeros
julia> zeros(2,3) 2x3 Array{Float64,2}: 0.0 0.0 0.0 0.0 0.0 0.0
 ones(m, n)
creates a array/matrix of ones
julia> ones(2,3) 2x3 Array{Float64,2}: 1.0 1.0 1.0 1.0 1.0 1.0
 eye(n)
creates an identity matrix I (called "eye", to avoid confusion with imaginary numbers):
julia> eye(3, 3) 3x3 Array{Float64,2}: 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0
eye(3)
does the same job as eye(3, 3)
.
 diagm(x)
uses the values in an array to create a matrix with that diagonal. For example, to put the first six integers into the diagonal of a 6 by 6 matrix:
julia> diagm(1:6) 6x6 Array{Int64,2}: 1 0 0 0 0 0 0 2 0 0 0 0 0 0 3 0 0 0 0 0 0 4 0 0 0 0 0 0 5 0 0 0 0 0 0 6
(You can specify a different diagonal by providing a second argument.)
 rand(m, n)
creates an mrow by ncolumn matrix full of random numbers:
julia> rand(2, 3) 2×3 Array{Float64,2}: 0.488552 0.657078 0.895564 0.0190633 0.0120305 0.772106
 rand(range, m, n)
creates a matrix full of numbers in the supplied range:
julia> rand(1:6, 3, 3) 3x3 Array{Int64,2}: 4 4 1 3 2 3 6 3 3
 randn(m, n)
creates an mrow by ncolumn matrix full of normallydistributed random numbers with mean 0 and standard deviation 1.
As well as the zeros()
, ones()
functions, there are trues()
, falses()
, fill()
, and fill!()
functions as well.
The trues()
and falses()
functions fill arrays with the Boolean values true or false:
julia> trues(3, 4) 3x4 BitArray{2}: true true true true true true true true true true true true
You can use fill()
to create an array with a specific value, i.e. an array of repeating duplicates:
julia> fill(42, 9), 9element Array{Int64,1}: 42 42 42 42 42 42 42 42 42 julia> fill("hi", 2, 2) 2x2 Array{String,2}: "hi" "hi" "hi" "hi"
With fill!()
, the exclamation mark (!
) or "bang" is to warn you that you're about to change the contents of an existing array (a useful indication that's adopted throughout Julia).
julia> a = zeros(10) 10element Array{Float64,1}: 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 julia> fill!(a, 42) 10element Array{Float64,1}: 42.0 42.0 42.0 42.0 42.0 42.0 42.0 42.0 42.0 42.0
Let's change an array of falses to trues:
julia> trueArray = falses(3,3) 3x3 BitArray{2}: false false false false false false false false false
julia> fill!(trueArray, true) 3x3 BitArray{2}: true true true true true true true true true
julia> trueArray 3x3 BitArray{2}: true true true true true true true true true
You can use linspace()
and logspace()
functions to create vectorlike arrays, followed by reshape()
to change them into 2D arrays:
julia> a = reshape(linspace(0, 100, 30), 10, 3) 10×3 Base.ReshapedArray{Float64, 2, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Tuple{}}:
0.0 34.4828 68.9655 3.44828 37.931 72.4138 6.89655 41.3793 75.8621 10.3448 44.8276 79.3103 13.7931 48.2759 82.7586 17.2414 51.7241 86.2069 20.6897 55.1724 89.6552 24.1379 58.6207 93.1034 27.5862 62.069 96.5517 31.0345 65.5172 100.0
The result is a 10 by 3 array featuring evenlyspaced numbers between 0 and 100.
Repeating elements to fill arrays[edit]
Two useful functions for creating arrays by repeating smaller ones are repmat()
and repeat()
.
The syntax for the first is repmat(A, n, m)
, the source array is repeated by n
times in the first dimension (rows), and m
times in the second (columns).
You don't have to supply the second dimension, just supply how many rows you want:
julia> repmat([1, 2, 3], 2) 6element Array{Int64,1}: 1 2 3 1 2 3 julia> repmat([1 2 3], 2) 2x3 Array{Int64,2}: 1 2 3 1 2 3
The second option specifies the extra columns:
julia> repmat([1, 2, 3], 2, 3) 6x3 Array{Int64,2}: 1 1 1 2 2 2 3 3 3 1 1 1 2 2 2 3 3 3 julia> repmat([1 2 3], 2, 3) 2x9 Array{Int64,2}: 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
The repeat()
function lets you create arrays by duplicating rows and columns of a source array. The inner
and outer
options determine whether rows and/or columns are repeated. For example, inner = [2, 3]
makes an array with two copies of each row and three copies of each column:
julia> repeat([1, 2], inner = [2, 3]) 4x3 Array{Int64,2}: 1 1 1 1 1 1 2 2 2 2 2 2
By contrast, here's outer = [2,3]
:
julia> repeat([1, 2], outer = [2, 3]) 4x3 Array{Int64,2}: 1 1 1 2 2 2 1 1 1 2 2 2
Array constructor[edit]
The Array()
function builds arrays of a specific type for you:
julia> Array{Int64}(6) 6element Array{Int64,1}: 4547140064 4545812016 4545807696 4545807696 4545807888 0
This is uninitialized; the oddlooking numbers are simply the old contents of the memory before it was assigned to hold the new array.
julia> Array{Int64}(2, 2) 2x2 Array{Int64,2}: 140237854510080 140237854535680 140237850941552 140237950729104
The Array
constructor can construct an array of arrays:
julia> Array[1:3, 4:6] 2element Array{Array,1}: [1,2,3] [4,5,6]
With the reshape()
function, you could of course just create a simple array and then change its shape:
julia> reshape([1, 2, 3, 4, 5, 6, 7, 8], 2, 4) 2x4 Array{Int64,2}: 1 3 5 7 2 4 6 8
The same techniques can be used to create 3D arrays. Here's a 3D array of strings:
julia> Array{String}(2, 3, 4) 2x3x4 Array{String,3}: [:, :, 1] = #undef #undef #undef #undef #undef #undef
[:, :, 2] = #undef #undef #undef #undef #undef #undef
[:, :, 3] = #undef #undef #undef #undef #undef #undef
[:, :, 4] = #undef #undef #undef #undef #undef #undef
Each element is set to 'undefined' — #undef
.
Arrays of arrays[edit]
It's easy to create an array of arrays. Sometimes you want to specify the original contents:
julia> a = Array[[1, 2], [3,4]] 2element Array{Array,1}: [1, 2] [3, 4]
julia> push!(a, rand(1:100, 5)) 3element Array{Array,1}: [1, 2] [3, 4] [4, 71, 82, 60, 48]
julia> push!(a, rand(1:100, 5)) 4element Array{Array,1}: [1,2] [3,4] [4, 71, 82, 60, 48] [4, 22, 52, 5, 14]
or you might want to create them empty:
julia> a = Array{Int}[] 0element Array{Array{Int64,N} where N,1}
julia> push!(a, [1, 2, 3]) 1element Array{Array{Int64,N} where N,1}: [1, 2, 3]
julia> push!(a, [4, 5, 6]) 2element Array{Array{Int64,N} where N,1}: [1, 2, 3] [4, 5, 6]
You can use Vector
as an alias for Array
:
julia> a = Vector{Int}[[1, 2], [3, 4]] 2element Array{Array{Int64,1},1}: [1, 2] [3, 4]
julia> push!(a, rand(1:100, 5)) 3element Array{Array{Int64, 1},1}: [1, 2] [3, 4] [12, 65, 53, 1, 82] julia> a[2] 2element Array{Int64,1}: 3 4 julia> a[2][1] 3
Copying arrays[edit]
If you have an existing array and want to create another array having the same dimensions, you can use the similar()
function:
julia> a = collect(1:10); julia> b = similar(a) 10element Array{Int64,1}: 0 0 0 0 0 0 0 0 0 0
Notice that the array dimensions are copied, but the values aren't. You can, though, change the type and dimensions anyway, so they don't have to be that similar:
julia> c = similar(b, String, (2, 2)) 2x2 Array{String,2}: #undef #undef #undef #undef
And in any case there's a copy()
function.
Matrix operations: using arrays as matrices[edit]
In Julia, a 2D array can be used as a matrix. All the functions available for working on arrays can be used (if the dimensions and contents permit) as matrices.
A quick way of typing a matrix is to separate the elements using spaces (to make rows) and to use semicolons to separate the rows. So:
julia> [1 0 ; 0 1]
2x2 Array{Int64,2}:
1 0
0 1


You could also do this:
julia> id = reshape([1, 2, 3, 4], 2, 2) 2×2 Array{Int64,2}: 1 3 2 4
which takes a standard array and reshapes it to run in two rows and two columns. Notice that the matrix is filled column by column.
If you don't use commas or semicolons:
julia> [1 2 3 4]
you'll create a single row array/matrix:
1x4 Array{Int64,2}: 1 2 3 4
In each case, notice the 2 in the braces following the type value. This indicates a 2dimensional array.
You can create an array of arrays by sticking two arrays next to each other, like this:
julia> [[1, 2, 3], [4, 5, 6]] 2element Array{Array{Int64,1},1}: [1, 2, 3] [4, 5, 6]
When you omit the comma, you're placing columns next to each and you'll get this:
julia> [[1, 2, 3] [4, 5, 6]] 3×2 Array{Int64,2}: 1 4 2 5 3 6
Accessing the contents[edit]
To access the elements of an array or matrix, follow the name of the array by the element number in square brackets. Here's a 1D array:
julia> a = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
Here's the fifth element:
julia> a[5] 50
The first element is index number 1. Julia is one of the languages that starts indexing elements in lists and arrays starting at 1, rather than 0. (And thus it's in the elite company of Matlab, Mathematica, Fortran, Lua, and Smalltalk, while most of the other programming languages are firmly in the opposite camp of 0based indexers.)
The last element is referred to as end (not 1, as in some other languages):
julia> a[end] 100
Similarly, you can access the second to last element with
julia> a[end1] 90
(with similar syntax for the third to last element and so on).
You can provide a bunch of index numbers, enclosed in a pair of brackets:
julia> a[[3,6,2]] 3element Array{Int64,1}: 30 60 20
julia> a[2:2:end] 5element Array{Int64,1}: 20 40 60 80 100
Here's a 2D array, with the rows separated by semicolons:
julia> a2 = [1 2 3; 4 5 6; 7 8 9] 3x3 Array{Int64,2}: 1 2 3 4 5 6 7 8 9 julia> a2[1] 1
If you just ask for one element of a 2D array, you'll receive it as if the array is unwound column by column, i.e. down first, then across. In this case you'll get 4, not 2:
julia> a2[2] 4
Asking for row then column works as you expect:
julia> a2[1, 2] 2
which is row 1, column 2. Here's row 1, column 3:
julia> a2[1, 3] 3
but don't get the row/column indices wrong:
julia> a2[1, 4] ERROR: BoundsError: attempt to access 3×3 Array{Int64,2} at index [1, 4] Stacktrace: [1] getindex(::Array{Int64,2}, ::Int64, ::Int64) at ./array.jl:498
By the way, there's an alternative way of obtaining elements from arrays: the getindex()
function:
julia> getindex(a2, 1, 3) 3 julia> getindex(a2, 1, 4) ERROR: BoundsError: attempt to access 3×3 Array{Int64,2} at index [1, 4] Stacktrace: [1] getindex(::Array{Int64,2}, ::Int64, ::Int64) at ./array.jl:498
Use the colon to indicate every row or column. For example, here's "every row, second column":
julia> a2[:, 2] 3element Array{Int64,1}: 2 5 8
and here's "second row, every column":
julia> a2[2, :] 3element Array{Int64,1}: 4 5 6
Elementwise and vectorized operations[edit]
Many Julia functions and operators are designed specifically to work with arrays. This means that you don't always have to work through each element of an array and process it individually.
A simple example is the use of the basic arithmetic operators. These can be used directly on an array if the other argument is a single value:
julia> a = collect(1:10); julia> a * 2 10element Array{Int64,1}: 2 4 6 8 10 12 14 16 18 20
and every element is multiplied by 2.
julia> a / 100 10element Array{Float64,1}: 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1
and every element is divided by 100.
These operations are described as operating elementwise. Many functions can operate on an array in this elementwise or vectorised way. For example, functions like sin()
and cos()
can be used elementwise on an array:
julia> sin(0:pi/12:2pi) 25element Array{Float64,1}: 0.0 0.258819 0.5 0.707107 0.866025 0.965926 1.0 0.965926 0.866025 ... 0.5 0.258819 2.44929e16
Some operators have their own elementwise version, which starts with a dot. These versions are the same as their nondotted versions, and work on the arrays element by element. For example, the counterpart of the multiply function (*) has an elementwise version (.*). This lets you multiply arrays or ranges together element by element:
julia> n1 = 1:6; julia> n2 = 100:100:600; julia> n1 .* n2 6element Array{Int64,1}: 100 400 900 1600 2500 3600
and the first element of the result is what you get by multiplying the first elements of the two arrays.
As well as the arithmetic operators, some of the comparison operators also have elementwise versions. For example, instead of using == in a loop to compare two arrays, use .==. Here are two arrays of ten numbers, one sequential, the other disordered, and an elementwise comparison to see how many elements of array b
happened to end up in the same place as array a
:
julia> a = 1:10; b=rand(1:10, 10); a .== b 10element BitArray{1}: true false true false false false false false false false
Dot syntax for vectorizing functions[edit]
Functions can be applied in vectorized/elementwise way to arrays with the dot syntax. Follow the function name with a dot/period before the opening parenthesis, and supply an array or range as an argument. For example, here's a simple function which multiplies two numbers together:
julia> f(a, b) = a * b f (generic function with 1 method) julia> f(2, 3) 6
To apply this function to an array, use the dot syntax:
julia> f.([1, 4, 2, 8, 7], 10) 5element Array{Int64,1}: 10 40 20 80 70
julia> f.(100, 1:10) 10element Array{Int64,1}: 100 200 300 400 500 600 700 800 900 1000
min() and max()[edit]
Watch out for max()
and min()
. You might think that max()
can be used on an array, like this, to find the largest element:
julia> r = rand(0:10, 10) 10element Array{Int64,1}: 3 8 4 3 2 5 7 3 10 10
but no…
julia> max(r) LoadError: MethodError: no method matching max(::Array{Int64,1}) ...
The max
function returns the largest of its arguments. To find the largest element in an array, you can use the related function maximum()
:
julia> maximum(r) 10
You can use max()
on two or more arrays to carry out an elementwise examination, returning another array containing the maximum values:
julia> r = rand(0:10, 10); s = rand(0:10, 10); t = rand(0:10,10);
julia> max(r, s, t) 10element Array{Int64,1}: 8 9 7 5 8 9 6 10 9 9
min()
and minimum()
behave in a similar way.
You can test each value of an array and change it in a single operation, using elementwise operators. Here's an array of random integers from 0 to 10:
julia> a = rand(0:10,10, 10) 10x10 Array{Int64,2}: 10 5 3 4 7 9 5 8 10 2 6 10 3 4 6 1 2 2 5 10 7 0 3 4 1 10 7 7 0 2 4 9 5 2 4 2 1 6 1 9 0 0 6 4 1 4 8 10 1 4 10 4 0 5 1 0 4 4 9 2 9 4 10 9 6 9 4 5 1 1 1 9 10 10 1 9 3 2 3 10 4 6 3 2 7 7 5 4 6 8 3 8 0 7 1 0 1 9 7 5
Now you can test each value for being equal to 0, then set only those elements to 11, like this:
julia> a[a .== 0] = 11;
julia> a 10x10 Array{Int64,2}: 10 5 3 4 7 9 5 8 10 2 6 10 3 4 6 1 2 2 5 10 7 11 3 4 1 10 7 7 11 2 4 9 5 2 4 2 1 6 1 9 11 11 6 4 1 4 8 10 1 4 10 4 11 5 1 11 4 4 9 2 9 4 10 9 6 9 4 5 1 1 1 9 10 10 1 9 3 2 3 10 4 6 3 2 7 7 5 4 6 8 3 8 11 7 1 11 1 9 7 5
If you're doing arithmetic on 2D matrices, you might want to read more about matrix arithmetic: Matrix arithmetic
Rows and Columns[edit]
With a 2D array, you use brackets, colons, and commas to extract individual rows and columns or ranges of rows and columns.
With this table:
julia> table = [r * c for r in 1:5, c in 1:5] 5x5 Array{Int64,2}: 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25
you can find a single row using the following (notice the comma):
julia> table[1,:] 1x5 Array{Int64,2}: 5element Array{Int64,1}: 1 2 3 4 5
and you can get a range of rows with a range followed by a comma and a colon:
julia> table[2:3,:] 2x5 Array{Int64,2}: 2 4 6 8 10 3 6 9 12 15
For columns, start with a colon followed by a comma:
julia> table[:, 2] 5element Array{Int64,1}: 2 4 6 8 10
On its own, the colon accesses the entire array:
julia> table[:] 25element Array{Int64,1}: 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25
To extract a range of columns:
julia> table[:, 2:3] 5x2 Array{Int64,2}: 2 3 4 6 6 9 8 12 10 15
Finding items in arrays[edit]
If you want to know whether an array contains an item, use the in()
function, which can be called in two ways:
julia> a = 1:10
julia> 3 in a true
Or phrased as a function call:
julia> in(3, a) true
There's a set of functions starting with find — such as find()
, findfirst()
, and findnext()
— that you can use to get the index or indices of array cells that match a specific value, or pass a test. Each of these has two or more more forms.
Here's an array of small primes (including 1, because it looks better):
julia> smallprimes = [1, 2, 3, 5, 7, 11, 13, 17, 19, 23];
To find the first occurrence of a number, and obtain its index, you can use the following method of the findfirst()
function:
julia> findfirst(smallprimes, 13) 7
so the first occurrence of 13 in the array is in the seventh cell:
julia> smallprimes[7] 13
There's another method of findfirst()
that lets you use a function that tests each element; it returns the index of the first one that passes the test. The two arguments are the function and the array.
julia> findfirst(x > x == 13, smallprimes) 7
The find()
function returns an array of indices, pointing to every element where the function returns true when applied to the value:
julia> find(isinteger, smallprimes) 10element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10
julia> find(iseven, smallprimes) 1element Array{Int64,1}: 2
Remember that these are arrays of index numbers, not the actual cell values. The indices can be used to extract the corresponding values using the standard square bracket syntax:
julia> smallprimes[find(isodd, smallprimes)] 9element Array{Int64,1}: 1 3 5 7 11 13 17 19 23
The findfirst()
version returns a single number — the index of the matching cell:
julia> findfirst(iseven, smallprimes) 2
julia> smallprimes[findfirst(iseven, smallprimes)] 2
The findnext()
function is very similar to the find()
and findfirst()
functions, but accepts an additional number that tells the functions to start the search from somewhere in the middle of the array, rather than from the beginning. For example, if findfirst(smallprimes,13)
finds the index of the first occurrence of the number 13 in the array, we can continue the search from there by using this value in findnext()
:
julia> findnext(isodd, smallprimes, 1 + findfirst(smallprimes,13)) 8
julia> smallprimes[ans] 17
The findin(A, B)
function returns the indices of the elements in array A where the elements of array B can be found:
julia> findin(smallprimes, [11, 5]) 2element Array{Int64,1}: 4 6
julia> smallprimes[4] 5
julia> smallprimes[6] 11
Notice the order in which the indices are returned.
Finding out about an array[edit]
With our 2D array:
julia> a2 = [1 2 3; 4 5 6; 7 8 9] 3x3 Array{Int64,2}: 1 2 3 4 5 6 7 8 9
we can find out more about it using the following functions:
ndims()
size()
length()
countnz()
ndims()
returns the number of dimensions, i.e. 1 for a vector, 2 for a table, and so on:
julia> ndims(a2) 2
size()
returns the row and column count of the array, in the form of a tuple:
julia> size(a2) (3,3)
length()
tells you how many elements the array contains:
julia> length(a2) 9
countnz()
tells you how many nonzero elements there are:
julia> countnz(a2) 9
For finding the inverse, determinant and other aspects of an array/matrix, see Manipulating matrices.
There are two related functions for converting between row/column numbers and array index numbers, ind2sub()
and sub2ind()
. Row 1, Column 1 is easy, of course  it's element 1, But Row 3, Column 7 is harder to work out. ind2sub()
takes an array, or the dimensions of an array, and an element index. For example, ind2sub(a2, 5)
returns the row and column for the fifth element of array a2
, in the form of a tuple:
julia> ind2sub(a2, 5) (2,2)
With a loop, you could look at the row/column numbers of every element in an array:
julia> for i in 1:length(a2) println(ind2sub(a2, i), " ", a2[i]) end (1,1) 1 (2,1) 4 (3,1) 7 (1,2) 2 (2,2) 5 (3,2) 8 (1,3) 3 (2,3) 6 (3,3) 9
To go in the reverse direction, use sub2ind()
and specify the dimensions of the array.
julia> a2[sub2ind((3, 3), 2, 1)] 4
finds you the element at row 2, column 1, for an array with dimensions (3,3).
Comparing arrays[edit]
union()
builds a new array that's the union or combination of two or more arrays. The operation removes duplicates, and the result contains a single version of each element:
julia> odds = collect(1:2:10) 5element Array{Int64,1}: 1 3 5 7 9
julia> evens = collect(2:2:10) 5element Array{Int64,1}: 2 4 6 8 10
julia> union(odds, evens) 10element Array{Int64,1}: 1 3 5 7 9 2 4 6 8 10
Notice that the ordering of the elements reflects the original order:
julia> union(1:5, 1:10, 5:1:5) 16element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10 0 1 2 3 4 5
intersect()
returns a new array that's the intersection of two or more arrays. The result contains one occurrence of each element, but only if it occurs in every array:
julia> intersect(1:10, 5:15) 5:10
julia> intersect(5:20, 1:15, 3:12) 5:12
setdiff()
finds the difference between two arrays, i.e. the elements that are in the first array but not the second:
julia> setdiff(1:15, 5:20) 4element Array{Int64,1}: 1 2 3 4
julia> setdiff(5:20, 1:15) 5element Array{Int64,1}: 16 17 18 19 20
Filtering[edit]
There's a set of related functions that let you work on an array's elements.
filter()
finds and keeps elements if they pass a test. Here, we're using the isodd()
function (passing it as a named function without parentheses, rather than a function call with parentheses) to filter (keep) everything in the array that's odd.
julia> filter(isodd, 1:10) 5element Array{Int64,1}: 1 3 5 7 9
Like many Julia functions, there's a version which changes the array. So filter()
returns a copy of the original, but filter!()
changes the array.
The count()
function is like filter()
, but just counts the number of elements that satisfy the condition:
julia> count(isodd, 1:100) 50
Also, the any()
function just tells you whether any of the elements satisfy the condition:
julia> any(isodd, 1:100) true
and the all()
function tells you if all of the elements satisfy the condition. Here, all()
checks to see whether filter()
did the job properly.
julia> all(isodd, filter(isodd, 1:100)) true
Random element of an array[edit]
To choose a random element from an array:
julia> a = collect(1:100); julia> a[rand(1:end)] 14
Other functions[edit]
Because arrays are fundamental to Julia, there are dozens of arrayhandling functions that can't be described here. But here are a few selections:
Find the extreme values of an array:
julia> a = rand(100:110, 10) 10element Array{Int64,1}: 109 102 104 108 103 110 100 108 101 101
julia> extrema(a) (100,110)
findmax() finds the maximum element and returns it and its index in a tuple:
julia> findmax(a) (110,6)
Functions such as sum()
, prod()
, mean()
, middle()
, do what you would expect:
julia> sum(a) 1046
julia> prod(a) 8302379321573251072
julia> mean(a) 104.6
julia> middle(a) 105.0
sum()
, mean()
, and prod()
also let you supply functions: the function is applied to each element and the results are then summed/meaned/prodded:
julia> sum(sqrt, 1:10) # the sum of the square roots of the first 10 integers 22.4682781862041 julia> mean(sqrt, 1:10) # the mean of the square roots of the first 10 integers 2.24682781862041
There are functions in the Combinatorics.jl package that let you find combinations and permutations of arrays. combinations()
finds all the possible combinations of elements in an array: you can specify how many elements in each combination:
julia> Pkg.add("Combinatorics") # (do this just once) julia> using Combinatorics julia> collect(combinations(a, 3)) 120element Array{Array{Int64,1},1}: [109,102,104] [109,102,108] [109,102,103] [109,102,110] [109,102,100] [109,102,108] [109,102,101] [109,102,101] [109,104,108] [109,104,103] [109,104,110] [109,104,100] [109,104,108] ⋮ [103,108,101] [103,101,101] [110,100,108] [110,100,101] [110,100,101] [110,108,101] [110,108,101] [110,101,101] [100,108,101] [100,108,101] [100,101,101] [108,101,101]
and permutations()
generates all permutations. There are a lot — in practice you probably don't need to use collect()
to collect the items into an array:
julia> collect(permutations(a)) 3628800element Array{Array{Int64,1},1}: [109,102,104,108,103,110,100,108,101,101] [109,102,104,108,103,110,100,108,101,101] [109,102,104,108,103,110,100,101,108,101] [109,102,104,108,103,110,100,101,101,108] [109,102,104,108,103,110,100,101,108,101] [109,102,104,108,103,110,100,101,101,108] [109,102,104,108,103,110,108,100,101,101] [109,102,104,108,103,110,108,100,101,101] [109,102,104,108,103,110,108,101,100,101] [109,102,104,108,103,110,108,101,101,100] [109,102,104,108,103,110,108,101,100,101] [109,102,104,108,103,110,108,101,101,100] [109,102,104,108,103,110,101,100,108,101] ⋮ [101,101,108,100,110,103,104,109,102,108] [101,101,108,100,110,103,104,109,108,102] [101,101,108,100,110,103,104,102,109,108] [101,101,108,100,110,103,104,102,108,109] [101,101,108,100,110,103,104,108,109,102] [101,101,108,100,110,103,104,108,102,109] [101,101,108,100,110,103,108,109,102,104] [101,101,108,100,110,103,108,109,104,102] [101,101,108,100,110,103,108,102,109,104] [101,101,108,100,110,103,108,102,104,109] [101,101,108,100,110,103,108,104,109,102] [101,101,108,100,110,103,108,104,102,109]
Modifying array contents: adding and removing elements[edit]
To add an item at the end of an array, use push!()
:
julia> a = collect(1:10); push!(a, 20) 11element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10 20
As usual, the exclamation mark reminds you that this function changes the array.
To add an item at the front, use the oddlynamed unshift!()
:
julia> unshift!(a, 0) 12element Array{Int64,1}: 0 1 2 3 4 5 6 7 8 9 10 20
To insert an element into an array at a given index, use the splice!()
function. For example, here's a list of numbers with an obvious omission:
julia> a = [1, 2, 3, 5, 6, 7, 8, 9] 8element Array{Int64,1}: 1 2 3 5 6 7 8 9
Use splice!()
to insert a sequence at a specific index. Julia returns the values that were replaced. The array grows larger to accommodate the new elements, and elements after the inserted sequence are pushed down. Let's insert the numbers 4:6 at index position 4, currently occupied by the number 5:
julia> splice!(a, 4:5, 4:6) 2element Array{Int64,1}: 5 6
You'll be tempted to check that the new values were inserted correctly:
julia> a 9element Array{Int64,1}: 1 2 3 4 5 6 7 8 9
Removing elements[edit]
If you don't supply a replacement, splice!()
can remove elements and move the rest of them along.
julia> a = collect(1:10); julia> splice!(a,5); julia> a 9element Array{Int64,1}: 1 2 3 4 6 7 8 9 10
To remove the last item:
julia> pop!(a) 10
and the first:
julia> shift!(a) 1
More aggressive modification of arrays (and similar data structures) can be made with functions such as deleteat!()
and splice!()
. You can find out the indices of elements in various ways. Once you know the indices, you can use deleteat!()
to delete an element, given its index number:
julia> a 7element Array{Int64,1}: 2 3 4 6 7 8 9 julia> findfirst(a, 6) 4 julia> deleteat!(a, findfirst(a, 6)) 6element Array{Int64,1}: 2 3 4 7 8 9
deleteat!()
accepts an iterator to specify the indices, so you can do this:
julia> deleteat!(a, 2:6) 1element Array{Int64,1}: 2
Remember that you can always remove a group of elements using a filter: see Filtering.
Other functions[edit]
If you want to do something to an array, there's probably a function to do it, and sometimes with an exclamation mark to remind you of the potential consequences. Here are a few more of these arraymodifying functions:
resize!()
append!()
prepend!()
empty!(a)
rotr90(a)
to rotate an array 90 degrees clockwise:
julia> rotr90([1 2 3 ; 4 5 6]) 3x2 Array{Int64,2}: 4 1 5 2 6 3
circshift(a)
to moves the elements around in a circle by a number of steps:
julia> circshift(1:6, 1) 6element Array{Int64,1}: 6 1 2 3 4 5
This function can also do circular shifts on 2D arrays too. For example, here's a table:
julia> table = collect(r*c for r in 1:5, c in 1:5) 5×5 Array{Int64,2}: 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25
By supplying a tuple you can move rows and columns. For example: moving the columns by 0 and the rows by 1 moves the first dimension by 0 and the second by 1. The first dimension is downwards, the second rightwards:
julia> circshift(table, (0, 1)) 5×5 Array{Int64,2}: 5 1 2 3 4 10 2 4 6 8 15 3 6 9 12 20 4 8 12 16 25 5 10 15 20
Setting the contents of arrays[edit]
To set the contents of an array, specify the indices on the lefthand side of an assignment expression:
julia> a = collect(1:10); julia> a[9]= 9 9
To check that the array has really changed:
julia> print(a) [1,2,3,4,5,6,7,8,9,10]
You can set a bunch of elements at the same time:
julia> a[3:6] = 5 5 julia> print(a) [1,2,5,5,5,5,7,8,9,10]
And you can set a sequence of elements to a suitable sequence of values:
julia> a[3:9] = collect(9:1:3) 7element Array{Int64,1}: 9 8 7 6 5 4 3
Notice here that, although Julia shows the 7 element slice as the return value, in fact the whole array has been modified:
julia> a 10element Array{Int64,1}: 1 2 9 8 7 6 5 4 3 10
You can set ranges to a single value in one operation:
julia> a[1:5] = 0 0 julia> a 10element Array{Int64,1}: 0 0 0 0 0 6 7 8 9 10 julia> a[1:10] = 1 1 julia> print(a) [1,1,1,1,1,1,1,1,1,1]
As an alternative to the square bracket notation, there's a function call version that does the same job of setting array contents, setindex!()
:
julia> setindex!(a, 1:10, 10:1:1) 10element Array{Int64,1}: 10 9 8 7 6 5 4 3 2 1
You can refer to the entire contents of an array using the colon separator without start and end index numbers, i.e. [:]
. For example, after creating the array a
:
julia> a = collect(1:10);
we can refer to the contents of this array a
using a[:]
:
julia> b = a[:] 10element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10 julia> b[3:6] 4element Array{Int64,1}: 3 4 5 6
Passing arrays to functions[edit]
A function can't modify a variable passed to it as an argument, but it can change the contents of a container passed to it.
Consider the following function, that changes its argument to 5:
julia> function set_to_5(x) x = 5 end set_to_5 (generic function with 1 method)
julia> x = 3 3
julia> set_to_5(x) 5
julia> x 3
Although the x
inside the function is changed, the x
outside the function isn't. Variable names in functions are local to the function.
But, you can modify the contents of a container, such as an array. The next function uses the [:]
syntax to access the contents of the container x
, rather than change the value of the variable x
:
julia> function fill_with_5(x) x[:] = 5 end fill_with_5 (generic function with 1 method)
julia> x = collect(1:10) 10element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10
julia> fill_with_5(x) 5
julia> x 10element Array{Int64,1}: 5 5 5 5 5 5 5 5 5 5
If, instead of accessing the container variable's contents, you try to change the variable itself, it won't work. For example, the following function definition creates an array of 5s in temp
and then attempts to change the argument x
to be temp
.
julia> function fail_to_fill_with_5(x) temp = similar(x) for i in 1:length(x) temp[i] = 5 end x = temp end fail_to_fill_with_5 (generic function with 1 method)
julia> x = collect(1:10) 10element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10
julia> fail_to_fill_with_5(x) 10element Array{Int64,1}: 5 5 5 5 5 5 5 5 5 5
It returns an array which looks promising, but:
julia> x 10element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10
You can change elements of the array, but you can't change the variable so that it points to a different array. In other words, your function isn't allowed to change the binding between the argument and the array that was passed to it.
Julia's way of handling function arguments is described as “passbysharing”. An array isn't copied when you pass it to a function (that would be very inefficient for large arrays).
Matrix arithmetic[edit]
For matrixonmatrix arithmetic action, you can:
 add (+) and subtract ():
julia> A = reshape(1:12, 3, 4)
3x4 Array{Int64,2}:
1 4 7 10
2 5 8 11
3 6 9 12


julia> B = ones(3,4)
3x4 Array{Float64,2}:
1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0


julia> A + B
3x4 Array{Float64,2}:
2.0 5.0 8.0 11.0
3.0 6.0 9.0 12.0
4.0 7.0 10.0 13.0


julia> A  B
3x4 Array{Float64,2}:
0.0 3.0 6.0 9.0
1.0 4.0 7.0 10.0
2.0 5.0 8.0 11.0


 multiply (*), assuming the dimensions are compatible, so m1 * m2
is possible if last(size(m1)) == first(size(m2))
. Note the difference between matrix multiplication and elementwise matrix multiplication. Here's a matrix A
:
julia> A = [1 2 ; 3 4]
2x2 Array{Int64,2}:
1 2
3 4


and here's matrix B
:
julia> B = [10 11 ; 12 13]
2x2 Array{Int64,2}:
10 11
12 13


The .*
operator multiplies them elementwise:
julia> A .* B
2x2 Array{Int64,2}:
10 22
36 52


Compare this with matrix multiplication, A * B
:
julia> A * B
2x2 Array{Int64,2}:
34 37
78 85


which is:
julia> [1 * 10 + 2 * 12 1 * 11 + 2 * 13 ; 3 * 10 + 4 * 12 3 * 11 + 4 * 13] 2x2 Array{Int64,2}: 34 37 78 85
 division of two matrices. You can use the backslash (\) for left division:
julia> A = rand(1:9, 3, 3) 3x3 Array{Int64,2}: 5 4 3 8 7 7 9 3 7
julia> B = rand(1:9, 3, 3) 3x3 Array{Int64,2}: 6 5 5 6 7 5 7 2 7
julia> A \ B 3x3 Array{Float64,2}: 2.01961 0.411765 1.84314 0.254902 1.35294 0.0392157 1.70588 0.823529 1.35294
and the forward slash (/) right or slash division:
julia> A / B 3x3 Array{Float64,2}: 4.0 2.0 1.0 0.285714 0.714286 0.285714 5.07143 3.07143 0.428571
With a matrix and a scalar, you can add, subtract, multiply, and divide:
julia> A + 1 3x3 Array{Int64,2}: 6 5 4 9 8 8 10 4 8
julia> [1 2 3 4 5] * 2 1x5 Array{Int64,2}: 2 4 6 8 10
julia> A  1 3x3 Array{Int64,2}: 4 3 2 7 6 6 8 2 6
julia> A * 2 3x3 Array{Int64,2}: 10 8 6 16 14 14 18 6 14
julia> A / 2 3x3 Array{Float64,2}: 2.5 2.0 1.5 4.0 3.5 3.5 4.5 1.5 3.5
and more besides:
julia> A // 2 3x4 Array{Rational{Int64},2}: 1//2 2//1 7//2 5//1 1//1 5//2 4//1 11//2 3//2 3//1 9//2 6//1
julia> A .< 6 3x3 BitArray{2}: true true true false false false false true false
You can multiply matrix and a vector (the matrixvector product), if the arrays have compatible shapes. Here's the matrix A:
julia> A = reshape(1:12, 3, 4)
3x4 Array{Int64,2}:
1 4 7 10
2 5 8 11
3 6 9 12


and here's a vector V:
julia> V = collect(1:4)
4element Array{Int64,1}:
1
2
3
4


The *
operator multiplies them:
julia> A * V
3element Array{Int64,1}:
70
80
90


The dot or inner product (aTb) can be found using the dot()
function:
julia> dot([1:3...], [21:23...])
134


julia> (1 * 21) + (2 * 22) + (3 * 23) 134
The two arguments must have the same length. You can also use the dot operator, which you can obtain in the REPL by typing "\cdot" followed by a tab:
julia> [1:3] ⋅ [21:23] 134
Joining arrays and matrices[edit]
You can use hcat()
and vcat()
to join matrices together, if their dimensions permit.
hcat()
keeps the first dimension and extends (joins) in the second, vcat()
keeps the second dimension and extends the first.
Here are two 3 by 4 matrices:
julia> A = reshape(1:12, 3, 4) 3x4 Array{Int64,2}: 1 4 7 10 2 5 8 11 3 6 9 12
julia> B = reshape(100:100:1200, 3, 4) 3x4 Array{Int64,2}: 100 400 700 1000 200 500 800 1100 300 600 900 1200
hcat(A, B)
makes an array that still has 3 rows, but extends/joins the columns:
julia> hcat(A, B) 3x8 Array{Int64,2}: 1 4 7 10 100 400 700 1000 2 5 8 11 200 500 800 1100 3 6 9 12 300 600 900 1200
vcat(A, B)
keeps the 4 columns, but extends to 6 rows:
julia> vcat(A, B) 6x4 Array{Int64,2}: 1 4 7 10 2 5 8 11 3 6 9 12 100 400 700 1000 200 500 800 1100 300 600 900 1200
You'll probably find the shortcuts useful:
 [A ; B ] is
vcat(A, B)
 [A B ] is
hcat(A, B)
vec()
flattens a matrix into a vector, turning it into a (or what some call a 'column') vector:
julia> vec(ones(3, 4)) 12element Array{Float64,1}: 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
There's also an hvcat()
function ([A B; C D;]
) that does both.
You can use hcat()
to convert an array of arrays to a matrix (using the hcatsplat):
julia> a = Array[[1, 2], [3, 4], [5, 6]] 3element Array{Array{T,N},1}: [1, 2] [3, 4] [5, 6] julia> hcat(a...) 2x3 Array{Int64,2}: 1 3 5 2 4 6
Julia arrays are 'columnmajor'. This means that you read down the columns:
1 3 2 4
whereas 'rowmajor' arrays are to be read across, like this:
1 2 3 4
Columnmajor order is used in Fortran, R, Matlab, GNU Octave, and by the BLAS and LAPACK engines (the "bread and butter of highperformance numerical computation"). Rowmajor order is used in C/C++, Mathematica, Pascal, Python, C#/CLI/.Net and others.
Growing or extending arrays[edit]
Often you want to create an array and then add more to it, or 'grow' it. You can do this with vcat()
and hcat()
, but be aware that both these operations create new temporary arrays and copy elements, so they don't always produce the fastest code. A better way is to use push!
. This is an efficient operation that extends the array. You can reshape the array later:
julia> a = [] julia> for i = 1:80 push!(a, i) end julia> a 80element Array{Any,1}: 1 2 3 4 5 6 7 8 9 ⋮ 75 76 77 78 79 80
reshape()
lets you change the dimensions of an array. You can supply the dimensions or use a colon (:
) to ask Julia to calculate valid dimensions:
julia> reshape(a, 10, :) 10x8 Array{Any,2}: 1 11 21 31 41 51 61 71 2 12 22 32 42 52 62 72 3 13 23 33 43 53 63 73 4 14 24 34 44 54 64 74 5 15 25 35 45 55 65 75 6 16 26 36 46 56 66 76 7 17 27 37 47 57 67 77 8 18 28 38 48 58 68 78 9 19 29 39 49 59 69 79 10 20 30 40 50 60 70 80
reshape(a, (10, div(length(a), 10)))
would have the same effect.
push!()
doesn't let you push new rows to a 2D array or matrix. The best way to do the job is to work on a 1D array, as above, adding more elements at the end, and then use reshape()
to convert it to two dimensions. If necessary, use transpose()
to flip the matrix.
Manipulating matrices[edit]
To transpose an array or matrix, there's an equivalent '
operator for the transpose()
function, to swap rows and columns:
julia> M = reshape(1:12, 3, 4) 3×4 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: 1 4 7 10 2 5 8 11 3 6 9 12
julia> transpose(M) 4x3 Array{Int64,2}: 1 2 3 4 5 6 7 8 9 10 11 12
julia> M' 4x3 Array{Int64,2}: 1 2 3 4 5 6 7 8 9 10 11 12
To find the determinant of a square matrix, use det()
:
julia> A = rand(2:10, 3, 3) 3x3 Array{Int64,2}: 8 8 2 6 9 6 9 2 10
julia> det(A) 438.00000000000006
inv()
finds the inverse of a square matrix, if it has one. (If the determinant of the matrix is zero, it won't have an inverse.)
julia> inv(A) 3x3 Array{Float64,2}: 0.178082 0.173516 0.0684932 0.0136986 0.141553 0.0821918 0.157534 0.127854 0.0547945
rank()
finds the rank of the matrix, and nullspace()
finds the basis for the nullspace.
julia> A 3x4 Array{Int64,2}: 1 4 7 10 2 5 8 11 3 6 9 12
julia> rank(A) 2
julia> nullspace(A) 4x2 Array{Float64,2}: 0.475185 0.272395 0.430549 0.717376 0.564458 0.617566 0.519821 0.172585
trace()
sums the diagonal of a square matrix:
julia> s = reshape(1:9, 3, 3) 3x3 Array{Int64,2}: 1 4 7 2 5 8 3 6 9
julia> trace(s) 15
Applying functions to matrices[edit]
There are a number of functions that can be applied to a matrix:
 sum()
adds every element:
julia> A = reshape(1:9, 3, 3) 3×3 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: 1 4 7 2 5 8 3 6 9
julia> sum(A) 45
You can specify a dimension if you want to sum just columns or rows. So to sum columns, specify dimension 1:
julia> sum(A, 1) 1x3 Array{Int64,2}: 6 15 24
To sum rows, specify dimension 2:
julia> sum(A, 2) 3x1 Array{Int64,2}: 12 15 18
 mean()
finds the mean of the values in the matrix:
julia> mean(A) 5.0
As with sum()
, you can specify a dimension, so that you can find the mean of columns (use dimension 1) or rows (use dimension 2):
julia> mean(A, 1) 1x3 Array{Float64,2}: 2.0 5.0 8.0
julia> mean(A, 2) 3x1 Array{Float64,2}: 4.0 5.0 6.0
 the min(A, B) and max(A, B) functions compare two (or more) arrays element by element, returning a new array with the largest (or smallest) values from each:
julia> A = rand(1:2:1, 3, 3) 3x3 Array{Int64,2}: 1 1 1 1 1 1 1 1 1
julia> B = rand(2:4:2, 3, 3) 3x3 Array{Int64,2}: 2 2 2 2 2 2 2 2 2
julia> max(A, B) 3x3 Array{Int64,2}: 2 2 2 2 1 2 2 2 2
julia> min(A,B) 3x3 Array{Int64,2}: 1 1 1 1 2 1 1 1 1
prod()
multiplies a matrix's elements together:
julia> A = reshape(collect(BigInt(1):25), 5, 5) 5×5 Array{BigInt,2}: 1 6 11 16 21 2 7 12 17 22 3 8 13 18 23 4 9 14 19 24 5 10 15 20 25 julia> prod(A) 15511210043330985984000000
You can specify a dimension if you want to multiply just columns or rows. To multiply the elements of columns together, specify dimension 1; for rows, use dimension 2:
julia> prod(A, 1) 1x5 Array{Int64,2}: 120 30240 360360 1860480 6375600
julia> prod(A, 2) 5x1 Array{Int64,2}: 22176 62832 129168 229824 375000
Matrix norms[edit]
Vector norms[edit]
The Euclidean norm, , is found by norm(x)
:
julia> X = [2, 4, 5] 3element Array{Int64,1}: 2 4 5 julia> norm(X) # Euclidean norm 6.708203932499369 julia> norm(x, 1) # 1norm of the vector, the sum of element magnitudes 11.0
If X is a 'row' vector:
julia> X = [2 4 5] 1x3 Array{Int64,2}: 2 4 5 julia> norm(X) 6.708203932499369 julia> norm(X, 1) 5.0
The Euclidean distance between vectors and , given by , is found by norm(x  y)
:
julia> norm([1 2 3]  [2 4 6]) 3.741657386773941 julia> norm([1, 2, 3]  [2, 4, 6]) 3.741657386773941
The angle between two vectors and is :
acos(dot(a,b)/(norm(a)*norm(b)))
Matrix norms[edit]
Here's the 1norm of a matrix (the maximum absolute column sum):
julia> B = [5 4 2 ; 1 2 3; 2 1 0] 3x3 Array{Int64,2}: 5 4 2 1 2 3 2 1 0
julia> norm(B, 1) 8.0
And here's the infinity norm (the maximum absolute row sum):
julia> norm(B, Inf) 11.0
The Euclidean norm()
is the default:
julia> norm([2 3 ; 4 6]), sqrt(2^2 + 3^2 + 4^2 + 6^2) (8.062257748298547,8.06225774829855)
Scaling and rotating matrices[edit]
 scale!(A, n)
scales every element of the matrix by a scale factor n:
julia> A = reshape(1:12, 3, 4) 3x4 Array{Int64,2}: 1 4 7 10 2 5 8 11 3 6 9 12
julia> scale!(A, 2) 3x4 Array{Int64,2}: 2 8 14 20 4 10 16 22 6 12 18 24
There are rotation and circularshifting functions too:
julia> rot180(A) 3x4 Array{Int64,2}: 12 9 6 3 11 8 5 2 10 7 4 1
julia> circshift(A, (1, 1)) 3×4 Array{Int64,2}: 12 3 6 9 10 1 4 7 11 2 5 8
Here's flipdim()
julia> flipdim(A, 1) 3x4 Array{Int64,2}: 3 6 9 12 2 5 8 11 1 4 7 10
julia> flipdim(A, 2) 3x4 Array{Int64,2}: 10 7 4 1 11 8 5 2 12 9 6 3
squeeze()
and reshape()
can be used to change the dimensions of a matrix. For example, this is how you can use squeeze()
to collapse a row vector (1 by 4) into a 4 by 1 array:
julia> a = [1 2 3 4] 1x4 Array{Int64,2}: 1 2 3 4
julia> ndims(a) 2
julia> b = squeeze(a, 1) 4element Array{Int64,1}: 1 2 3 4
julia> ndims(b) 1
Sorting arrays[edit]
Julia has a flexible sort()
function that returns a sorted copy of an array, and a companion sort!()
version that changes the array so that it's sorted.
You can usually use sort()
without options and obtain the results you'd hoped for:
julia> rp = randperm(10) 10element Array{Int64,1}: 6 4 7 3 10 5 8 1 9 2
julia> sort(rp) 10element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10
You could even sort 2D arrays:
julia> a = reshape(rand(1:20, 20), 4, 5) 4x5 Array{Int64,2}: 19 13 4 10 10 6 20 19 18 12 17 7 15 14 9 1 16 8 7 13
julia> sort(a, 1) # columns, dimension 1 4x5 Array{Int64,2}: 1 7 4 7 9 6 13 8 10 10 17 16 15 14 12 19 20 19 18 13
julia> sort(a, 2) # rows, dimension 2 4x5 Array{Int64,2}: 4 10 10 13 19 6 12 18 19 20 7 9 14 15 17 1 7 8 13 16
although there are more powerful alternatives in sortrows()
and sortcolumns()
— see below for details.
The sortperm()
function is similar to sort()
, but it doesn't return a sorted copy of the collection. Instead it returns a list of indices that could be applied to the collection to produce a sorted version:
julia> r = rand(100:110, 10) 10element Array{Int64,1}: 103 102 110 108 108 108 104 109 106 106
julia> sortperm(r) 10element Array{Int64,1}: 2 1 7 9 10 4 5 6 8 3
julia> r[sortperm(r)] 10element Array{Int64,1}: 102 103 104 106 106 108 108 108 109 110
Sort by and comparisons[edit]
If you need more than the default sort offers, use the by
and lt
keywords and provide your own functions for processing and comparing elements during the sort.
sort by[edit]
The by
function processes each element before comparison and provides the 'key' for the sort. A typical example is the task of sorting a list of numbers in string form. Here's the list:
julia> r = ["1E10", "150", "25", "3", "1.5", "1E10", "0.5", ".999"];
If you use the default sort, the numbers appear in the order in which the characters appear in Unicode/ASCII:
julia> sort(r) 8element Array{ASCIIString,1}: ".999" "0.5" "1.5" "150" "1E10" "1E10" "25" "3"
To sort the numbers by their value, pass the parse()
function to by
:
julia> sort(r, by = x > parse(x)) 8element Array{ASCIIString,1}: "1E10" "0.5" ".999" "1.5" "3" "25" "150" "1E10"
The strings are sorted 'by' their value. Notice that the by
function you supply produces the sort key, but the original elements appear in the final result.
Anonymous functions can be useful when sorting arrays. Here's a 10 rows by 2 columns array of tuples:
julia> table = collect(enumerate(rand(1:100, 10))) 10element Array{(Int64,Int64),1}: (1,86) (2,25) (3,3) (4,97) (5,89) (6,58) (7,27) (8,93) (9,98) (10,12)
You can sort this by the second element of each tuple, not the first, by supplying an anonymous function to by
that points to the second element of each. The anonymous function says, given an object x
to sort, sort by the second element of x
:
julia> sort(table, by = x > x[2]) 10element Array{(Int64,Int64),1}: (3,3) (10,12) (2,25) (7,27) (6,58) (1,86) (5,89) (8,93) (4,97) (9,98)
Sorting by multiple columns[edit]
You can supply a tuple of "column" identifiers in the by
function, if you want to sort by more than one column.
julia> a = [[2, 2, 2, 1], [1, 1, 1, 8], [2, 1, 2, 2], [1, 2, 2, 5], [2, 1, 1, 4], [1, 1, 2, 7], [1, 2, 1, 6], [2, 2, 1, 3]] ;
julia> sort(a, by = col > (col[1], col[2], col[3])) 8element Array{Array{Int64,1},1}: [1,1,1,8] [1,1,2,7] [1,2,1,6] [1,2,2,5] [2,1,1,4] [2,1,2,2] [2,2,1,3] [2,2,2,1]
This sorts the array first by column 1, then by column 2, then by column 3.
Redefining 'less than'[edit]
By default, sorting uses the builtin isless()
function when comparing elements. In a sorted array, the first element is less than the second.
You can change this behaviour by passing a different function to the lt
keyword. This function should compare two elements and return true if they're sorted, i.e. if the first element is 'less than' the second, using some definition of 'less than'. The sorting process compares pairs of elements repeatedly until every element of the array is in the right place.
For example, suppose you want to sort an array of words according to the number of vowels in each word; i.e. the more vowels a word has, the earlier in the sorted results it occurs. For example, the word "orange" will be considered to be "less than" the word "lemon", because it has more vowels.
First we'll need a function that counts vowels:
vowelcount(string) = count(c > (c in "aeiou"), lowercase(string))
Now you can pass an anonymous function to sort()
that compares the vowel count of two elements using this function and then returns the element with a higher count in each case:
sentence = split("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); sort(sentence, lt = (x,y) > vowelcount(x) > vowelcount(y))
The result is that the word with the most vowels appears first:
19element Array{SubString{ASCIIString},1}: "adipisicing" "consectetur" "eiusmod" "incididunt" "aliqua." "labore" "dolore" "Lorem" "ipsum" "dolor" "amet," "elit," "tempor" "magna" "sit" "sed" "do" "ut" "et"
The sort()
function also lets you specify a reverse sort  after the by
and lt
functions (if used) have done their work, a true value passed to rev
reverses the result.
Sorting 2D arrays[edit]
To sort arrays with two or more dimensions, including matrices, you should use sortrows()
and sortcolumns()
.
Here's a 10 by 10 array.
julia> table = rand(1:4, 10, 10) 10x10 Array{Int64,2}: 1 1 4 1 3 1 3 2 2 2 2 3 2 3 3 4 3 4 1 4 1 1 1 2 2 3 3 2 1 3 2 2 3 1 4 2 1 1 3 2 3 4 2 1 4 4 1 1 3 3 4 1 2 1 4 3 4 1 4 1 1 1 3 2 4 3 4 3 3 1 2 2 3 3 1 4 3 4 3 3 3 3 2 4 3 2 2 2 3 4 4 4 3 1 2 3 3 3 3 3
By default, sortrows()
just sorts the array by the first element in each row:
julia> sortrows(table) 10x10 Array{Int64,2}: 1 1 4 1 3 1 3 2 2 2 1 1 1 2 2 3 3 2 1 3 1 1 3 2 4 3 4 3 3 1 2 3 2 3 3 4 3 4 1 4 2 2 3 1 4 2 1 1 3 2 2 2 3 3 1 4 3 4 3 3 3 4 2 1 4 4 1 1 3 3 3 3 2 4 3 2 2 2 3 4 4 1 2 1 4 3 4 1 4 1 4 4 3 1 2 3 3 3 3 3
— notice that 1 1 4
comes before 1 1 1
. But, as with sort()
, sortrows()
lets you specify the keys, and you can provide a tuple of column indicators, such as (x[1], x[2], x[3]), which sorts the array first by the element in column 1, then by the element in column 2, then by column 3.
julia> sortrows(table, by = x > (x[1], x[2], x[3])) 10x10 Array{Int64,2}: 1 1 1 2 2 3 3 2 1 3 1 1 3 2 4 3 4 3 3 1 1 1 4 1 3 1 3 2 2 2 2 2 3 1 4 2 1 1 3 2 2 2 3 3 1 4 3 4 3 3 2 3 2 3 3 4 3 4 1 4 3 3 2 4 3 2 2 2 3 4 3 4 2 1 4 4 1 1 3 3 4 1 2 1 4 3 4 1 4 1 4 4 3 1 2 3 3 3 3 3
The sortcols()
function does a similar job, sorting by column rather than row.
Tuples[edit]
A tuple is an ordered sequence of elements, like an array. A tuple is represented by parentheses and commas, rather than the square brackets used by arrays. Tuples are mostly good for small fixedlength collections — they're used everywhere in Julia, for example, as argument lists and for returning multiple values from functions.
The important difference between arrays and tuples is that tuples are immutable. Other than that, tuples work in much the same way as arrays, and many array functions can be used on tuples too:
julia> t = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) (1,2,3,4,5,6,7,8,9,10)
julia> t (1,2,3,4,5,6,7,8,9,10)
julia> t[6:end] (6,7,8,9,10)
You can have twodimensional tuples:
julia> t = ((1, 2), (3, 4)) ((1,2),(3,4))
julia> t[1] (1,2)
julia> t[1][2] 2
But you can't change a tuple:
julia> t[1] = 0 LoadError: MethodError: no method matching set index!...
And, because you can't modify tuples, you can't use any of the functions like push!()
that you use with arrays:
julia> a = [1,2,3]; julia> push!(a,4) 4element Array{Int64,1}: 1 2 3 4
julia> t = (1,2,3); julia> push!(t,4) LoadError: MethodError: no method matching push!