By: Steven Whitaker
Re-posted from: https://glcs.hashnode.dev/basic-data-structures
Julia is a relatively new,free, and open-source programming language.It has a syntaxsimilar to that of other popular programming languagessuch as MATLAB and Python,but it boasts being able to achieve C-like speeds.
Julia provides several useful data structuresfor storing and manipulating data.Some of these data structures,like arrays and dictionaries,are ubiquitous in Julia codebecause of their usefulnessand wide applicability.Others, like sets,have more limited usesbut neverthelessstill are useful data structures.
In this post,we will learn aboutarrays, dictionaries, and setsin Julia.We will discuss how to construct themand describe various functionsfor working with and manipulating them.
This post assumes you already have Julia installed.If you haven’t yet,check out our earlierpost on how to install Julia.
Arrays
One of the most basic and ubiquitous data structuresis the array.Arrays are used for storing values,iterating through values,and even representing mathematical vectors and matrices.
The basic array type in Julia is Array{T,N}
,where T
is the type of the elements in the array(or an abstract supertype of the elementsif not all elements are of the same type),and N
is the number of array dimensions.For example,a list of strings would be of type Array{String,1}
,while a matrix of numbers would be of type Array{Float64,2}
.
Constructing Arrays
There are various waysto construct arrays.One common wayis to construct an arraydirectly from the valuesit will contain:
julia> ["some", "strings"]2-element Vector{String}: "some" "strings"julia> [1 2; 3 4]2x2 Matrix{Int64}: 1 2 3 4
(Note that Vector{T}
is equivalent to Array{T,1}
and that Matrix{T}
is equivalent to Array{T,2}
.)
Another common wayto construct arraysis using array comprehensions.An array comprehensioncreates an arrayby looping through a collection of valuesand computing an array elementfor each value.For example,the following creates an arraycontaining the squaresof the first five natural numbers:
julia> [x^2 for x = 1:5]5-element Vector{Int64}: 1 4 9 16 25
Multidimensional comprehensions also exist:
julia> [(x - 2)^2 + (y - 3)^2 <= 1 for x = 1:3, y = 1:5]3x5 Matrix{Bool}: 0 0 1 0 0 0 1 1 1 0 0 0 1 0 0
We can also create uninitialized arrays,either by passing undef
to the array constructoror by calling similar
:
julia> Array{Int,1}(undef, 1)1-element Vector{Int64}: 6303840julia> similar([1.0, 2.0])2-element Vector{Float64}: 6.94291544947797e-310 6.94291610129443e-310
(Note that the seemingly random numbers abovecome from whatever bits happen to be setin the memory allocated for the arrays.)
To create an array of zeros,call zeros
:
julia> zeros(2, 3)2x3 Matrix{Float64}: 0.0 0.0 0.0 0.0 0.0 0.0
Inspecting Arrays
Information about an arraycan be obtained using various functions.
length
gives the number of elementsin an array:
julia> length([1, 2, 3])3julia> length(zeros(2, 3))6
size(x)
gives the size of x
,while size(x, d)
gives the sizeof the d
th dimension:
julia> size([1, 2, 3])(3,)julia> size(zeros(2, 3))(2, 3)julia> size(zeros(2, 3), 2)3
ndims
gives the number of dimensionsof an array:
julia> ndims(zeros(1, 2, 3, 4, 5, 6))6
And eltype
gives the typeof the elements of an array:
julia> eltype(["two", "strings"])Stringjulia> eltype([2, "different types"])Any
Array Operations
Accessing array elementsis achieved using brackets:
julia> a = [10, 20, 30];julia> a[2]20
(Note that arrays use one-based indexingin Julia.)
A similar syntax is usedto modify the contents of an array:
julia> a[1] = 00julia> a3-element Vector{Int64}: 0 20 30
Use commas (,
) to separate indexesfor different dimensions,and use a colon (:
)to select all the valuesalong a dimension:
julia> m = [1 2; 3 4]2x2 Matrix{Int64}: 1 2 3 4julia> m[1,2]2julia> m[:,1]2-element Vector{Int64}: 1 3
Multiple indexes can be provided:
julia> a[[1, 3]]2-element Vector{Int64}: 0 30
To assign a single valueto multiple array locations,use broadcasting:
julia> a[2:3] .= 02-element view(::Vector{Int64}, 2:3) with eltype Int64: 0 0julia> a3-element Vector{Int64}: 0 0 0
Arrays are also iterable,meaning we can loop throughthe values of an array:
julia> words = ["this", "is", "a", "sentence"];julia> for w in words println(w) endthisisasentence
Arrays as Stacks/Queues/Dequeues
Julia also provides some functionsthat allow arrays to be usedin a similar wayas stacks, queues, and dequeues.For example,push!(array, x)
inserts x
at the end of an array,and pop!(array)
removes the last elementof an array.Similarly,pushfirst!
and popfirst
act on the beginning of an array.
Ranges
Ranges are another useful type of array,often used for loopingand array indexing.
The simplest syntaxfor creating a rangeis a:b
,which creates a rangethat starts at a
and includes all valuesa + 1
, a + 2
, etc.,as long as a + n <= b
.For example,1:5
contains 1
, 2
, 3
, 4
, and 5
,while 1.0:2.5
contains 1.0
and 2.0
.
A step size, s
, can also be specified,as in a:s:b
.In this case, the spacing between valuesin the rangeis s
instead of 1
.
To create a range of N
pointsbetween a
and b
, inclusive,use range(a, b, N)
.
Unlike Array
s,ranges are immutable,meaning their elementscan’t be modified.If modifying an element of a rangeis necessary,it must first be convertedinto an Array
by calling collect
:
julia> r = 1:21:2julia> r[1] = 10ERROR: CanonicalIndexError: setindex! not defined for UnitRange{Int64}julia> r_arr = collect(r)2-element Vector{Int64}: 1 2julia> r_arr[1] = 10; r_arr2-element Vector{Int64}: 10 2
That concludes our discussion of arrays,so now let’s move on to dictionaries.
Dictionaries
Another very common data structureis the dictionary.A dictionary is a mappingfrom keys to values:give a dictionary a key,and it will returnthe value associated with that key(if present).
In Julia,dictionaries are of type Dict{K,V}
,where K
is the type of the keys,and V
is the type of the values.
Dictionaries are constructedby providing key-value pairs:
julia> d = Dict("key1" => 1, "key2" => 2, "key3" => 3)Dict{String, Int64} with 3 entries: "key2" => 2 "key3" => 3 "key1" => 1
(Note that a => b
creates a Pair
in Julia.)
Indexing a dictionaryuses the same syntaxas indexing an array,just using keysinstead of array indexes:
julia> d["key2"]2
Use haskey
to checkfor the presence of a key:
julia> haskey(d, "key3")truejulia> haskey(d, "nope")false
Dictionaries can also be updated:
julia> d["key1"] = 99999999julia> d["newkey"] = -9999-9999julia> dDict{String, Int64} with 4 entries: "key2" => 2 "key3" => 3 "key1" => 9999 "newkey" => -9999
Use delete!(dict, key)
to delete the mappingfor the given key,if present.
We can also iteratethrough the keys and/or valuesof a dictionary:
- Iterating keys:
for k in keys(dict)
- Iterating values:
for v in values(dict)
- Iterating both:
for (k, v) in dict
That wraps up our discussion of dictionaries,so now we will move on to sets.
Sets
A set is a collection of unique elements.In Julia,sets are of type Set{T}
,where T
is the typeof the elements of the set.Sets are usefulfor their efficient set operations,such as membership testing,union
, and intersect
.
Create an empty set of Float64
values as follows:
julia> s = Set{Float64}()Set{Float64}()
Use push!
to add valuesto the set,noticing that the set changesonly if the value does not already existin the set:
julia> push!(s, 1.0);julia> push!(s, 1.2);julia> push!(s, 3.14)Set{Float64} with 3 elements: 1.2 3.14 1.0julia> push!(s, 1.0)Set{Float64} with 3 elements: 1.2 3.14 1.0
Use union
to take the unionof two sets:
julia> t = Set([1.0, 2.0])Set{Float64} with 2 elements: 2.0 1.0julia> r = s t # type \cup<tab> to get the union symbolSet{Float64} with 4 elements: 1.2 2.0 3.14 1.0
(Note that s t == union(s, t)
.)
Use intersect
to take the intersectionof two sets:
julia> r t # type \cap<tab> to get the intersection symbolSet{Float64} with 2 elements: 2.0 1.0
(Note that s t == intersect(s, t)
.)
Finally,we can check if an elementbelongs to a setwith in
:
julia> 1.0 r # type \in<tab> to get the "is an element of" symboltrue
(Note that and
in
are interchangeable here.)
And with that,we conclude our overviewof some important Julia data structures.
Summary
In this post,we learned about a few data structuresthat Julia provides:arrays, dictionaries, and sets.We learned how to construct themand how to work with and manipulate them.
What are the most useful data structuresyou have used?Let us know in the comments below!
Have a better understandingof Julia’s basic data structures?Move on to thenext post to learn about multiple dispatch,one of Julia’s most distinctive features!Or,feel free to take a lookat our other Julia tutorial posts!
Additional Links
- Julia Documentation: Arrays
- Additional information about arrays.
- Julia Documentation: Collections and Data Structures
- Additional information about arrays, dictionaries, and sets.
- DataStructures.jl
- Package providing several more data structures,including priority queues, binary heaps, trees, and more.See the README for a complete list.