Videos related to this segment (click the title to watch)
01 JULIA1 - 3A: Primitive types, char and strings (9:37)
01 JULIA1 - 3B: One dimensional arrays (30:42)
01 JULIA1 - 3C: Multidimensional arrays (23:37)
01 JULIA1 - 3D: Tuples and named tuples (7:50)
01 JULIA1 - 3E: Dictionaries and sets (8:57)
01 JULIA1 - 3F: Date and times (19:11)

0103 Predefined types

Some stuff to set-up the environment..

julia> cd(@__DIR__)
julia> using Pkg
julia> Pkg.activate(".") # If using a Julia version different than 1.10 please uncomment and run the following line (reproductibility guarantee will hower be lost) # Pkg.resolve() # Pkg.instantiate() # run this if you didn't in Segment 01.01 Activating project at `~/work/SPMLJ/SPMLJ/buildedDoc/01_-_JULIA1_-_Basic_Julia_programming`
julia> using Random
julia> Random.seed!(123)Random.TaskLocalRNG()
julia> using InteractiveUtils # loaded automatically when working... interactively

Primitive types

Primitive types have a fixed number of bits associated to them. Examples of them are Int64, Float64, Char, UInt64, UFloat64, Int32, Float32,... Even primitive types can be custom defined. See the "custom types" segment !

Char and Strings - Char, String

julia> a = "Hello World ""Hello World "
julia> b = a[2]'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)
julia> typeof(b)Char
julia> b = a[3:end]"llo World "
julia> typeof(b) # a[2] = 'E' # error !String

Information...

julia> ismutable(a) # long story.... https://github.com/JuliaLang/julia/issues/30210true
julia> length(a)12
julia> findfirst(isequal('o'), a)5
julia> findnext(isequal('o'), a, 6)8
julia> occursin("world",a)false
julia> occursin(lowercase("world"),lowercase(a))true
julia> using Unicode
julia> occursin(Unicode.normalize("world", casefold=true),Unicode.normalize(a, casefold=true))true
julia> endswith(a,"ld ")true
julia> startswith(a,"Mooo")false
julia> occursin(r"H*.d ", a)true

Modifications..

julia> lowercase(a)"hello world "
julia> lowercasefirst(a)"hello World "
julia> split(a, " ")3-element Vector{SubString{String}}: "Hello" "World" ""
julia> replace(a,"World" => "Universe")"Hello Universe "
julia> strip(a)"Hello World"

Concatenation..

julia> a = "Hello"; b= "World""World"
julia> c = join([a,b]," ")"Hello World"
julia> c = a*" "*b"Hello World"
julia> c = string(a," ",b)"Hello World"
julia> c = "$a $b" # interpolation # Conversion.."Hello World"
julia> a = parse(Int64,"2012")2012
julia> b = string(2019)"2019"
Warning

Attention not to confuse the string function with the String type and the String() constructor!

to know more...

julia> methodswith(String,supertypes=true); # where any argument is a String or any parent type (such e.g. AbstractString)

See also https://docs.julialang.org/en/v1/manual/strings/

Arrays - Array{T,N}

Array{T,NDims} A parameteric type where the type of the content and the number of dimensions define the specific type

Tip

Vector{T} is an alias for Array{T,1} and Matrix{T} is an alias for Array{T,2}, but there isn't anything "special" for 1 or 2 dimensions compared to more dimensions

Vectors - Array{T,1}

One-dimensions arrays in julia are treated as column vector, and, depending on the inner type, they can be stored efficiently contiguously in memory. However they are NOT the same of a single column of a two dimensions array. A row vector is necessarily instead a single row of a 2 dimensions array.

julia> a = [1,2,3]3-element Vector{Int64}:
 1
 2
 3
julia> b = [1 ; 2 ; 3 ;;] # This syntax requires Julia >= 1.73×1 Matrix{Int64}: 1 2 3
julia> a == bfalse

Initialisation

julia> a = [1,2,3]; #= or =# a = [1;2;3]3-element Vector{Int64}:
 1
 2
 3
julia> a = [1; 6:-2:2; 10] # notes: (a) the semicolon, (b) the range includes BOTH the extremes5-element Vector{Int64}: 1 6 4 2 10
julia> a = [[1,2],[3,4]] # nested vectors. Each elements can have a different lenght, but rules of linear algebra doesn't apply2-element Vector{Vector{Int64}}: [1, 2] [3, 4]
Danger

Don't confuse nested vectors with multi-dimensional arrays!

Empty (zero-elements) arrays:

julia> a = []Any[]
julia> a = Int64[]Int64[]
julia> a = [1,2,3]3-element Vector{Int64}: 1 2 3
julia> b = [1,"pizza","beer"]3-element Vector{Any}: 1 "pizza" "beer"
julia> a = Array{Int64,1}()Int64[]
Warning

Watch out for the difference between a = Array{Int64,1}() and a = Array{Int64,1}

julia> a = Vector{Int64}()Int64[]

n-elements initialisation:

julia> n = 33
julia> T = Int64Int64
julia> zeros(n) # zeros (Float64)3-element Vector{Float64}: 0.0 0.0 0.0
julia> zeros(T,n) # zeros (casted as type T)3-element Vector{Int64}: 0 0 0
julia> ones(n) # ones (Float64)3-element Vector{Float64}: 1.0 1.0 1.0
julia> ones(T,n) # ones (casted of type T)3-element Vector{Int64}: 1 1 1
julia> Array{T,1}(undef,n) # garbage3-element Vector{Int64}: 140142704513200 140142709059264 0
julia> fill(2,3)3-element Vector{Int64}: 2 2 2

Accessing Vectors

julia> a = [10,20,30,40,50,60,70,80,90]9-element Vector{Int64}:
 10
 20
 30
 40
 50
 60
 70
 80
 90
julia> a[1]10
julia> a[end]90
julia> a[[1; 6:-2:2; 8]] # indicised by a vector of positions5-element Vector{Int64}: 10 60 40 20 80

Collecting iterators into vectors

julia> aRange = 3:2:73:2:7
julia> a = collect(aRange)3-element Vector{Int64}: 3 5 7
julia> a = [3:2:7;] # alternative3-element Vector{Int64}: 3 5 7
julia> typeof(aRange)StepRange{Int64, Int64}
julia> typeof(aRange) <: AbstractArray # Everywhere an AbstractArray is expected, you can provide a range insteadtrue

Common operations with vectors

julia> a = [1,2,3]3-element Vector{Int64}:
 1
 2
 3
julia> reverse(a), a[end:-1:1] # Other way to revert an array([3, 2, 1], [3, 2, 1])
julia> vcat([1,2,3],[4,5],6)6-element Vector{Int64}: 1 2 3 4 5 6
julia> push!(a,4) # add as individual elements4-element Vector{Int64}: 1 2 3 4
julia> append!(a,5) # add as many new elements5-element Vector{Int64}: 1 2 3 4 5
Functions with exclamation marks

By convention functions that modify one of their parameters (and usually this is the first one) are named with an exclamation mark at the end. Remember (most) unicode characters are valid in functions or variable names.

julia> push!([[1,2],[3,4,5]],[6,7])3-element Vector{Vector{Int64}}:
 [1, 2]
 [3, 4, 5]
 [6, 7]
julia> append!([1,2,3,4,5],[6,7])7-element Vector{Int64}: 1 2 3 4 5 6 7
julia> pop!(a)5
julia> a4-element Vector{Int64}: 1 2 3 4
julia> popfirst!(a)1
julia> deleteat!(a,2)2-element Vector{Int64}: 2 4
julia> pushfirst!([2,3],1)3-element Vector{Int64}: 1 2 3
julia> a = [2,1,3,1]4-element Vector{Int64}: 2 1 3 1
julia> sort(a) # also `sort!(a)``4-element Vector{Int64}: 1 1 2 3
julia> unique(a) # also `unique!(a)`3-element Vector{Int64}: 2 1 3
julia> in(1,a) # also available as operator: `if 2 in a [...] end`true
julia> length(a) # number of elements contained in all the dimensions4
julia> size(a),size(a,1) # number of elements by dimension((4,), 4)
julia> minimum(a)1
julia> min(a...)1
...

"..." is called the splat operator and it is used to convert the elements in a vector into a tuple of separate elements in a function call, like the example above

julia> min(4,7,3)3
julia> minimum([4,7,9])4
julia> argmin([4,2,5,2])2
julia> sum([1,2,3])6
julia> cumsum([1,2,3])3-element Vector{Int64}: 1 3 6
julia> empty!(a) # only for VectorsInt64[]
julia> using Random
julia> shuffle([1,2,3]) # also shuffle!([1,2,3])3-element Vector{Int64}: 1 3 2
julia> isempty(a)true
julia> findall(x -> x == 1, [2,1,3,1]) # anonymous function returning an array of bools, findall then return the indexes2-element Vector{Int64}: 2 4
julia> findfirst(x -> x == 1, [2,1,3,1])2
julia> myComparitionWith1(i) = i==1myComparitionWith1 (generic function with 1 method)
julia> findall(x -> myComparitionWith1(x), [2,1,3,1])2-element Vector{Int64}: 2 4
julia> filter(i -> i > 2, [1,2,3,4])2-element Vector{Int64}: 3 4

Delete [7,2,5] from an1:10` array:

julia> data     = [1:10;]10-element Vector{Int64}:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
julia> toDelete = [7,5,2]3-element Vector{Int64}: 7 5 2
julia> deleteat!(data, findall(x -> x in toDelete, data))7-element Vector{Int64}: 1 3 4 6 8 9 10
julia> for (i,value) in enumerate([10,20,30]) # iterator that returns an index/element tuple println("$i - $value") end1 - 10 2 - 20 3 - 30
julia> names = ["Marc", "Anne"]2-element Vector{String}: "Marc" "Anne"
julia> sex = ['M','F']2-element Vector{Char}: 'M': ASCII/Unicode U+004D (category Lu: Letter, uppercase) 'F': ASCII/Unicode U+0046 (category Lu: Letter, uppercase)
julia> age = [25,20]2-element Vector{Int64}: 25 20
julia> for zippedElements in zip(names,sex,age) # iterator that returns tuples made with one element per argument of zip println(zippedElements) end("Marc", 'M', 25) ("Anne", 'F', 20)

Multidimensional arrays - Array{T,N}

Initialisation

julia> a = [[1,2,3] [4,5,6]] # By column, i.e. elements of the first column, elements of the second column, ...3×2 Matrix{Int64}:
 1  4
 2  5
 3  6
julia> a = [1 4; 2 5; 3 6] # By row, i.e. elements of the first row, elements of the second row, ... # Empty (zero-elements) arrays:3×2 Matrix{Int64}: 1 4 2 5 3 6
julia> a = Array{Float64}(undef, 0, 0, 0) # using explicitly the constructor and explicitly giving zero for each wanted dimension0×0×0 Array{Float64, 3}

n-elements initialisation:

julia> (T,n,m,g,j) = (Int64,1,2,3,'a')(Int64, 1, 2, 3, 'a')
julia> a = zeros(n,m,g) # n,m,g-elements zeros array1×2×3 Array{Float64, 3}: [:, :, 1] = 0.0 0.0 [:, :, 2] = 0.0 0.0 [:, :, 3] = 0.0 0.0
julia> a = ones(n,m,g) # n,m,g-elements ones array1×2×3 Array{Float64, 3}: [:, :, 1] = 1.0 1.0 [:, :, 2] = 1.0 1.0 [:, :, 3] = 1.0 1.0
julia> a = Array{T,3}(undef,n,m,g) # n,m,g-elements array whose content is garbage1×2×3 Array{Int64, 3}: [:, :, 1] = 140147676691024 140147676691024 [:, :, 2] = 140147676691024 140147676691024 [:, :, 3] = 140147676691024 140147676691024
julia> a = fill(j,n,m,g) # n,m,g-elements array of identical j elements1×2×3 Array{Char, 3}: [:, :, 1] = 'a' 'a' [:, :, 2] = 'a' 'a' [:, :, 3] = 'a' 'a'
julia> a = rand(n,m,g) # n,m,g-elements array of of random numbers1×2×3 Array{Float64, 3}: [:, :, 1] = 0.890879 0.190907 [:, :, 2] = 0.525662 0.390588 [:, :, 3] = 0.044818 0.933353
julia> a = [3x + 2y + z for x in 1:2, y in 2:3, z in 1:2] # from using list comprehension2×2×2 Array{Int64, 3}: [:, :, 1] = 8 10 11 13 [:, :, 2] = 9 11 12 14

Accessing n-dimensional arrays

Access by indicating position

julia> a = [1 2 3 4; 5 6 7 8; 9 10 11 12]3×4 Matrix{Int64}:
 1   2   3   4
 5   6   7   8
 9  10  11  12
julia> a[2,1] # comma to separate the dimensions5
Warning

Don't confuse a[i,j] for selecting an element of a Matrix with a[i][j] to select the inner component of a nested array

julia> a[1,2:3]   # with a range on the second dimension2-element Vector{Int64}:
 2
 3
julia> a[[1,3],1] # with a vector of positions in the first dimension2-element Vector{Int64}: 1 9
julia> a[2,:] # with a full range (all values) in the second dimension, i.e. all columns value for row 24-element Vector{Int64}: 5 6 7 8
Warning

Note that when the data as only one element on a given dimension, julia reduces the dimensions automatically: the result of a[2,:] is NOT a row vector (that is a one-row matrix) but a one dimensional array

Access by a mask (boolean selection)

julia> b = [true false true false; true true true false; true false true false]3×4 Matrix{Bool}:
 1  0  1  0
 1  1  1  0
 1  0  1  0
julia> a[b] # always flatted array returned (need eventually reshaping, see later)7-element Vector{Int64}: 1 5 9 6 3 7 11
julia> size(a)              # returns a tuple (i.e. an immutable list) with the sizes of the n dimensions(3, 4)
julia> ndims(a) # return the number of dimensions of the array (e.g. `2` for a matrix)2
julia> reshape(a, 2,3,2)2×3×2 Array{Int64, 3}: [:, :, 1] = 1 9 6 5 2 10 [:, :, 2] = 3 11 8 7 4 12
julia> 2*3*2 == length(a)true
julia> b = rand(2,1,3)2×1×3 Array{Float64, 3}: [:, :, 1] = 0.5805599818745412 0.32723787925628356 [:, :, 2] = 0.5269959187969865 0.8362285750521512 [:, :, 3] = 0.04090613602769255 0.4652015053812224
julia> dropdims(b,dims=(2)) # remove the specified dimensions, provided that the specified dimension have only a single element2×3 Matrix{Float64}: 0.58056 0.526996 0.0409061 0.327238 0.836229 0.465202
julia> permutedims(a) # "swap" the dimensions4×3 Matrix{Int64}: 1 5 9 2 6 10 3 7 11 4 8 12
julia> reshape(a,4,3) # keep the column mayor order4×3 Matrix{Int64}: 1 6 11 5 10 4 9 3 8 2 7 12
julia> for slice in eachslice(a,dims=1) println(slice) end[1, 2, 3, 4] [5, 6, 7, 8] [9, 10, 11, 12]
julia> a = reshape(1:24, 3,4,2)3×4×2 reshape(::UnitRange{Int64}, 3, 4, 2) with eltype Int64: [:, :, 1] = 1 4 7 10 2 5 8 11 3 6 9 12 [:, :, 2] = 13 16 19 22 14 17 20 23 15 18 21 24
julia> for slice in eachslice(a,dims=1) println(slice) end[1 13; 4 16; 7 19; 10 22] [2 14; 5 17; 8 20; 11 23] [3 15; 6 18; 9 21; 12 24]
julia> a = [1 2;3 4; 5 6]3×2 Matrix{Int64}: 1 2 3 4 5 6
julia> selectdim(a,1,3) # Select an hyperplane on dimension 1 (rows) at position 3. Returns a view2-element view(::Matrix{Int64}, 3, :) with eltype Int64: 5 6

Flat to vector..

julia> a = [1 2; 3 4]2×2 Matrix{Int64}:
 1  2
 3  4
julia> vec(a) # shadow copy (different view of the underlying data)4-element Vector{Int64}: 1 3 2 4
julia> reshape(a,4) # shadow copy4-element Vector{Int64}: 1 3 2 4
julia> a[:] # allocate, as all slice operations do4-element Vector{Int64}: 1 3 2 4
julia> vcat([1 2; 3 4], [5 6; 7 8]) # works also for DataFrames4×2 Matrix{Int64}:
 1  2
 3  4
 5  6
 7  8
julia> hcat([1,2,3],[4,5,6]) # works also for DataFrames3×2 Matrix{Int64}: 1 4 2 5 3 6
julia> a = [1 2; 3 4]2×2 Matrix{Int64}: 1 2 3 4
julia> b = similar(a) # garbage inside2×2 Matrix{Int64}: 140145285662960 140145285663024 140145285662992 140145285663056
julia> cat(a,a,a,dims=3)2×2×3 Array{Int64, 3}: [:, :, 1] = 1 2 3 4 [:, :, 2] = 1 2 3 4 [:, :, 3] = 1 2 3 4

Sort by column (field)

julia> a = [[3,2,1] [20,30,20] [1000,3000,2000] [300,100,200]]3×4 Matrix{Int64}:
 3  20  1000  300
 2  30  3000  100
 1  20  2000  200
julia> idx = sortperm(a[:,3], rev=true) # return the positions that sort the 3rd column3-element Vector{Int64}: 2 3 1
julia> sortedMatrix = a[idx,:] # selected by using the sorted positions array on the row dimension3×4 Matrix{Int64}: 2 30 3000 100 1 20 2000 200 3 20 1000 300
julia> sortslices(a, dims=2) # by cols, using the first row to sort3×4 Matrix{Int64}: 3 20 300 1000 2 30 100 3000 1 20 200 2000
julia> sortslices(a, dims=1) # by rows, using the first column to sort3×4 Matrix{Int64}: 1 20 2000 200 2 30 3000 100 3 20 1000 300
julia> sortslices(a, dims=1, by = x -> (x[2],x[4])) # by rows, using second and fourth columns3×4 Matrix{Int64}: 1 20 2000 200 3 20 1000 300 2 30 3000 100

Basic linear algebra

julia> using LinearAlgebra
julia> a = [-1,2,3]3-element Vector{Int64}: -1 2 3
julia> b = [4,5,6]3-element Vector{Int64}: 4 5 6
julia> transpose(a)1×3 transpose(::Vector{Int64}) with eltype Int64: -1 2 3
julia> a'1×3 adjoint(::Vector{Int64}) with eltype Int64: -1 2 3
julia> norm(a) # l-2 by default3.7416573867739413
julia> norm(a,1)6.0

Vector products:

julia> dot(a,b)    # dot, aka "inner" product24
julia> a' * b == dot(a,b)true
julia> cross(a,b) # cross product3-element Vector{Int64}: -3 18 -13
julia> a .* b # element-wise product3-element Vector{Int64}: -4 10 18
julia> a * b'3×3 Matrix{Int64}: -4 -5 -6 8 10 12 12 15 18
julia> A = [1 2 3; 6 4 5; 7 8 9]3×3 Matrix{Int64}: 1 2 3 6 4 5 7 8 9
julia> A^(-1) # inverse3×3 Matrix{Float64}: -0.222222 0.333333 -0.111111 -1.05556 -0.666667 0.722222 1.11111 0.333333 -0.444444
julia> A^23×3 Matrix{Int64}: 34 34 40 65 68 83 118 118 142
julia> det(A) # determinant18.000000000000004
julia> transpose(A)3×3 transpose(::Matrix{Int64}) with eltype Int64: 1 6 7 2 4 8 3 5 9
julia> A'3×3 adjoint(::Matrix{Int64}) with eltype Int64: 1 6 7 2 4 8 3 5 9
Warning

Be aware that transpose works only for numerical types. When the matrix contains other types (e.g. strings), use permutedims

julia> diag(A)3-element Vector{Int64}:
 1
 4
 9
julia> I # operator that automatically scale to the context without actually building the matrixLinearAlgebra.UniformScaling{Bool} true*I
julia> A*I3×3 Matrix{Int64}: 1 2 3 6 4 5 7 8 9
julia> B = [1 2; 3 4]; B*I2×2 Matrix{Int64}: 1 2 3 4
julia> (evalues, evectors) = eigen(A)LinearAlgebra.Eigen{ComplexF64, ComplexF64, Matrix{ComplexF64}, Vector{ComplexF64}} values: 3-element Vector{ComplexF64}: -0.8056073109913213 - 0.7099395230053245im -0.8056073109913213 + 0.7099395230053245im 15.611214621982644 + 0.0im vectors: 3×3 Matrix{ComplexF64}: -0.267976-0.290703im -0.267976+0.290703im 0.239114+0.0im 0.777975-0.0im 0.777975+0.0im 0.485634+0.0im -0.426158+0.238381im -0.426158-0.238381im 0.840824+0.0im

Tuples - Tuple{T1,T2,...}

A "collection" similar to Array but:

  • Immutable
  • Can efficiently host heterogeneous types, as type information is stored for each individual element
  • Linear algebra doesn't apply (use StaticArray.jl package for that)

Can be tought as anonymous (immutable) structures Used to unpack multiple values, e.g. to store on inddividual variables the output of functions with multiple return value

Initialisation

julia> t = (1,2.5,"a",3)(1, 2.5, "a", 3)
julia> t = 1,2.5,"a",3(1, 2.5, "a", 3)
julia> typeof(t)Tuple{Int64, Float64, String, Int64}

Indexing

julia> t[1]1

Conversion

julia> v = [1,2,3]3-element Vector{Int64}:
 1
 2
 3
julia> t = (v...,) # note the comma(1, 2, 3)
julia> v2 = [t...]3-element Vector{Int64}: 1 2 3
julia> v3 = [i[1] for i in t]3-element Vector{Int64}: 1 2 3
julia> v4 = collect(t)3-element Vector{Int64}: 1 2 3
julia> v == v2 == v3 == v4true

Tuples with a variable number of same-type elements

While the tuple type normally include informations of the types of each elements, one by one, we may want to have a way to "summarise" this information by specifying that a certain number of elements, all of this type, are repeated. This is the task of the Vararg{T} and Vararg{T,N} arguments that must be specified as the last parameters of a Tuple type. The former one allows for a variable number of elements, and the latter one specific an exact number of elements:

julia> typeof(("aaa",1,10)) <: Tuple{String,Vararg{Int}}true
julia> typeof(("aaa",1,10)) <: Tuple{String,Vararg{Int,2}}true
julia> typeof(("aaa",1,10)) <: Tuple{String,Vararg{Int,3}}false
Tip

NTuple{N,T}is an alias forTuple{Vararg{T,N}}`

julia> typeof((1,10)) <: NTuple{2,Int}true

Named tuples - NamedTuple{T1,T2,...}

As the name suggests, named tuples are collection similar to ordinary tuples, but whose indexing can accept also a name:

julia> nt = (a=1, b=2.5)
       #nt = ("a"=1, "b"=2.5)    # Error !(a = 1, b = 2.5)
julia> typeof(nt)@NamedTuple{a::Int64, b::Float64}
julia> nt[1]1
julia> nt.a1
julia> keys(nt)(:a, :b)
julia> values(nt)(1, 2.5)
julia> for (k,v) in pairs(nt) println("$k - $v") enda - 1 b - 2.5
Warning

The keys of NamedTuples are symbols, not strings. We'll see symbols in the metaprogramming segment.

Conversion

julia> k = [:a,:b,:c]3-element Vector{Symbol}:
 :a
 :b
 :c
julia> v = [1,2,3]3-element Vector{Int64}: 1 2 3
julia> nt = NamedTuple(Dict(:a=>1,:b=>2,:c=>3)) # Order not guaranteed! We are "lucky" here(a = 1, b = 2, c = 3)
julia> nt = NamedTuple(Dict([k=>v for (k,v) in zip(k,v)])) # Same...(a = 1, b = 2, c = 3)
julia> v2 = [nt...]3-element Vector{Int64}: 1 2 3
julia> v3 = [i[1] for i in nt]3-element Vector{Int64}: 1 2 3
julia> v4 = collect(nt)3-element Vector{Int64}: 1 2 3
julia> v == v2 == v3 == v4true

Dictionaries - Dict{Tkey,TValue}

Dictionary are mutable, key-referenced containers:

MutableImmutable
Use positionArraysTuples
Use keysDictionariesNamed tuples
Warning

Note that order is not preserved. For insertion-order preservation see OrderedDict and for sorted dictionaries see SortedDict, both from the DataStructures.jl package.

Initialisation

julia> mydict = Dict(); #= or better =#  mydict = Dict{String,Int64}()Dict{String, Int64}()
julia> mydict = Dict('a'=>1, 'b'=>2, 'c'=>3)Dict{Char, Int64} with 3 entries: 'a' => 1 'c' => 3 'b' => 2

Indexing

julia> mydict['a']
       #mydict['d']     # error!1
julia> get(mydict,'d',0) # specific a default if key not found0

Adding/deleting/checking

julia> mydict['d'] = 44
julia> delete!(mydict,'d')Dict{Char, Int64} with 3 entries: 'a' => 1 'c' => 3 'b' => 2
julia> haskey(mydict, 'a')true
julia> in(('a' => 1), mydict)true
julia> typeof('a' => 1)Pair{Char, Int64}

Conversion

Array - > Dictionary

julia> map((i,j) -> mydict[i]=j, ['e','f','g'], [4,5,6])3-element Vector{Int64}:
 4
 5
 6
julia> mydictDict{Char, Int64} with 6 entries: 'f' => 5 'g' => 6 'a' => 1 'c' => 3 'e' => 4 'b' => 2
julia> k = [:a,:b,:c]3-element Vector{Symbol}: :a :b :c
julia> v = [1,2,3]3-element Vector{Int64}: 1 2 3
julia> mydict = Dict([k=>v for (k,v) in zip(k,v)])Dict{Symbol, Int64} with 3 entries: :a => 1 :b => 2 :c => 3

Dictionary -> Arrays

julia> collect(keys(mydict)) # keys or values alore return an iterator3-element Vector{Symbol}:
 :a
 :b
 :c
julia> collect(values(mydict))3-element Vector{Int64}: 1 2 3

Iteration

julia> for (k,v) in mydict
          println("$k is $v")
       enda is 1
b is 2
c is 3

Sets - Set{T}

julia> s = Set(); #= or better =# Set{Int64}()Set{Int64}()
julia> s = Set([1,2,3,4]) # Only a single `2` will be storedSet{Int64} with 4 elements: 4 2 3 1
julia> sSet{Int64} with 4 elements: 4 2 3 1
julia> push!(s,5)Set{Int64} with 5 elements: 5 4 2 3 1
julia> delete!(s,1)Set{Int64} with 4 elements: 5 4 2 3
julia> s2 = Set([4,5,6,7])Set{Int64} with 4 elements: 5 4 6 7
julia> intersect(s,s2)Set{Int64} with 2 elements: 5 4
julia> union(s,s2)Set{Int64} with 6 elements: 5 4 6 7 2 3
julia> setdiff(s,s2)Set{Int64} with 2 elements: 2 3

Date and time - Date, DateTime

julia> using Dates # a standard library module dealing with dates and times, including periods and calendars

While a DateTime is a more informative object it is also a much more complex one, as it has to deal with problems as the time zones and the daylight saving

Creation of a date or time object ("input")

From current (local) date/time...

julia> todayDate = today()2024-01-01
julia> nowTime = now()2024-01-01T22:55:13.377
julia> typeof(todayDate)Dates.Date
julia> typeof(nowTime)Dates.DateTime
julia> Date <: Dates.AbstractTimetrue
julia> DateTime <: Dates.AbstractTimetrue
julia> nowTimeUnix = time() # The so-called "Unix time, a 64bit integer counting the number of seconds since the beginning of the year 19701.7041497134011e9
julia> nowTime = Dates.unix2datetime(nowTimeUnix) # attention this is not local but UTC (Coordinated Universal Time - the Greenwitch time )!2024-01-01T22:55:13.401
julia> nowTime = Dates.now(Dates.UTC) # an other way to have UTC time2024-01-01T22:55:13.401
Tip

For Time Zone functionalities and conversion, use the external package TimeZone.jl

From a String...

julia> christmasDay      = Date("25 Dec 2030", "d u yyyy")2030-12-25
julia> newYearDay = Date("2031/01/01", "yyyy/m/d")2031-01-01
julia> christmasLunch = DateTime("2030-12-25T12:30:00", ISODateTimeFormat) # well known string datetime ISO8601 Format2030-12-25T12:30:00
julia> newYearEvenDinner = DateTime("Sat, 30 Dec 2030 21:30:00", RFC1123Format) # an othe well known format2030-12-30T21:30:00

Date and time formatters:

  • y Year digit (ef yyyy => 2030, yy => 30)
  • m Month digit (eg m => 3, mm => 03)
  • u Month name (eg "Jan")
  • U Month name long (eg "January")
  • e Day of week (eg "Tue")
  • E Day of week long (eg "Tuesday")
  • d Day of month (eg d => 3, dd => 03)
  • H Hour digit (eg H => 8, HH => 08)
  • M Minute digit (eg M => 0, MM => 00)
  • S Second digit (eg S => 0, SS => 00)
  • s Millisecond digit (eg .000, fixed 3 digits)

Note that the doubling for the digits matters only for using the formatters in the output (see later)

From a tuple of integers: y, m, d, H, M, S, s ...

julia> d  = Date(2030, 12)  # no need to give it all2030-12-01
julia> dt = DateTime(2030, 12, 31, 9, 30, 0, 0)2030-12-31T09:30:00

Date/Time extraction of information ("output")...

To String represerntation...

julia> Dates.format(newYearDay, "dd/m/yy")"01/1/31"
julia> Dates.format(christmasLunch, "dd/mm/yy H:M:SS")"25/12/30 12:30:00"

Other...

  • Date and DateTime...
julia> year(christmasDay)2030
julia> isleapyear(christmasDay)false
julia> month(christmasLunch)12
julia> monthname(christmasDay)"December"
julia> day(christmasDay)25
julia> dayofweek(christmasDay)3
julia> dayname(christmasDay)"Wednesday"
julia> daysofweekinmonth(christmasDay) # there are 4 Wednesdays in December 20304
julia> dayofweekofmonth(christmasDay) # and the 25th is the 4th of them4
  • Only datetime..
julia> hour(christmasLunch)12
julia> minute(christmasLunch)30
julia> second(christmasLunch)0

Periods and datetime arithmetics

julia> hollidayPeriod = newYearDay - christmasDay  # between dates is in days7 days
julia> longPeriod = Date(2035,6,1) - christmasDay1619 days
julia> mealPeriod = DateTime(2030,12,31,23,30) - newYearEvenDinner # between datetime is in milliseconds # newYearDay - newYearEvenDinner # error! no mixed93600000 milliseconds
julia> convert(DateTime,newYearDay)2031-01-01T00:00:00
julia> convert(Date,newYearEvenDinner) # possible information loss2030-12-30
julia> mealPeriod = convert(DateTime,newYearDay) - newYearEvenDinner95400000 milliseconds
julia> typeof(hollidayPeriod)Dates.Day
julia> typeof(mealPeriod)Dates.Millisecond

Period hierarchy:

  • Period
    • DatePeriod
      • Year
      • Month
      • Week
      • Day
    • TimePeriod
      • Hour
      • Minute
      • Second
      • Millisecond
      • Microsecond
      • Nanosecond
julia> # convert(Dates.Year,longPeriod)      # going up: error or inexacterror
       convert(Dates.Millisecond,longPeriod) # going down:  fine139881600000 milliseconds
julia> convert(Dates.Millisecond,mealPeriod)95400000 milliseconds
julia> canLongPeriod = Dates.canonicalize(longPeriod)231 weeks, 2 days
julia> typeof(canLongPeriod)Dates.CompoundPeriod

That the best we can get. We can't "easily" decompose a "period" in years or months... how many days in a month ? 31 or 30 ? And in an year ? A Period doesn't store information on when it starts. However we can make math with periods based on a specific date/time:

julia> nextChristmas                = christmasDay + Year(1) # We can use the constructors of the various periods2031-12-25
julia> christmasPresentsOpeningTime = christmasLunch + Hour(3)2030-12-25T15:30:00
julia> thisWeekdayNextCentury = dayname(today()+Year(100))"Saturday"

Ranges

julia> semesters = Dates.Date(2020,1,1):Dates.Month(6):Dates.Date(2022,1,1)Dates.Date("2020-01-01"):Dates.Month(6):Dates.Date("2022-01-01")
julia> collect(semesters)5-element Vector{Dates.Date}: 2020-01-01 2020-07-01 2021-01-01 2021-07-01 2022-01-01

Adjustments

Iterate the past/future days of a date untill some condition is true

julia> sundayBefChristmas = toprev(d -> Dates.dayname(d) == "Sunday", christmasDay)2030-12-22
julia> lastDayOfThisMonth = tonext(d -> Dates.day(d+Day(1)) == 1, today())2024-01-31

Find first or last weekday of {month,year} of a given date:

julia> lastTuesdayOfThisMonth = tolast(today(), 2, of=Month) # "2" stands for Tuesday2024-01-30
julia> firstSundayOfThisYear = tofirst(today(), 7, of=Year) # "7" stands for Sunday2024-01-07

View this file on Github.


This page was generated using Literate.jl.