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 Pkgjulia> Pkg.activate(".") # If using a Julia version different than 1.10 please uncomment and run the following line (reproducibility guarantee will however be lost) # Pkg.resolve() # Pkg.instantiate() # run this if you didn't in Segment 01.01Activating project at `~/work/SPMLJ/SPMLJ/buildedDoc/01_-_JULIA1_-_Basic_Julia_programming`julia> using Randomjulia> 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)Charjulia> 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/30210truejulia> length(a)12julia> findfirst(isequal('o'), a)5julia> findnext(isequal('o'), a, 6)8julia> occursin("world",a)falsejulia> occursin(lowercase("world"),lowercase(a))truejulia> using Unicodejulia> occursin(Unicode.normalize("world", casefold=true),Unicode.normalize(a, casefold=true))truejulia> endswith(a,"ld ")truejulia> startswith(a,"Mooo")falsejulia> 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")2012julia> b = string(2019)"2019"
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
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 3julia> b = [1 ; 2 ; 3 ;;] # This syntax requires Julia >= 1.73×1 Matrix{Int64}: 1 2 3julia> a == bfalse
Initialisation
julia> a = [1,2,3]; #= or =# a = [1;2;3]3-element Vector{Int64}: 1 2 3julia> a = [1; 6:-2:2; 10] # notes: (a) the semicolon, (b) the range includes BOTH the extremes5-element Vector{Int64}: 1 6 4 2 10julia> a = [[1,2],[3,4]] # nested vectors. Each elements can have a different length, but rules of linear algebra doesn't apply2-element Vector{Vector{Int64}}: [1, 2] [3, 4]
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 3julia> b = [1,"pizza","beer"]3-element Vector{Any}: 1 "pizza" "beer"julia> a = Array{Int64,1}()Int64[]
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 = 33julia> T = Int64Int64julia> zeros(n) # zeros (Float64)3-element Vector{Float64}: 0.0 0.0 0.0julia> zeros(T,n) # zeros (casted as type T)3-element Vector{Int64}: 0 0 0julia> ones(n) # ones (Float64)3-element Vector{Float64}: 1.0 1.0 1.0julia> ones(T,n) # ones (casted of type T)3-element Vector{Int64}: 1 1 1julia> Array{T,1}(undef,n) # garbage3-element Vector{Int64}: 140373385619536 140373385540144 0julia> 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 90julia> a[1]10julia> a[end]90julia> 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:7julia> a = collect(aRange)3-element Vector{Int64}: 3 5 7julia> a = [3:2:7;] # alternative3-element Vector{Int64}: 3 5 7julia> 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 3julia> 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 6julia> push!(a,4) # add as individual elements4-element Vector{Int64}: 1 2 3 4julia> append!(a,5) # add as many new elements5-element Vector{Int64}: 1 2 3 4 5
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 7julia> pop!(a)5julia> a4-element Vector{Int64}: 1 2 3 4julia> popfirst!(a)1julia> deleteat!(a,2)2-element Vector{Int64}: 2 4julia> pushfirst!([2,3],1)3-element Vector{Int64}: 1 2 3julia> a = [2,1,3,1]4-element Vector{Int64}: 2 1 3 1julia> sort(a) # also `sort!(a)``4-element Vector{Int64}: 1 1 2 3julia> unique(a) # also `unique!(a)`3-element Vector{Int64}: 2 1 3julia> in(1,a) # also available as operator: `if 2 in a [...] end`truejulia> length(a) # number of elements contained in all the dimensions4julia> size(a),size(a,1) # number of elements by dimension((4,), 4)julia> minimum(a)1julia> 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)3julia> minimum([4,7,9])4julia> argmin([4,2,5,2])2julia> sum([1,2,3])6julia> cumsum([1,2,3])3-element Vector{Int64}: 1 3 6julia> empty!(a) # only for VectorsInt64[]julia> using Randomjulia> shuffle([1,2,3]) # also shuffle!([1,2,3])3-element Vector{Int64}: 1 3 2julia> isempty(a)truejulia> findall(x -> x == 1, [2,1,3,1]) # anonymous function returning an array of booleans, findall then return the indexes2-element Vector{Int64}: 2 4julia> findfirst(x -> x == 1, [2,1,3,1])2julia> myComparitionWith1(i) = i==1myComparitionWith1 (generic function with 1 method)julia> findall(x -> myComparitionWith1(x), [2,1,3,1])2-element Vector{Int64}: 2 4julia> 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 10julia> toDelete = [7,5,2]3-element Vector{Int64}: 7 5 2julia> deleteat!(data, findall(x -> x in toDelete, data))7-element Vector{Int64}: 1 3 4 6 8 9 10julia> for (i,value) in enumerate([10,20,30]) # iterator that returns an index/element tuple println("$i - $value") end1 - 10 2 - 20 3 - 30julia> 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 20julia> 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 6julia> 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 6julia> 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.0julia> 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.0julia> a = Array{T,3}(undef,n,m,g) # n,m,g-elements array whose content is garbage1×2×3 Array{Int64, 3}: [:, :, 1] = 140376378875728 140376378867136 [:, :, 2] = 140376378875728 140376378875728 [:, :, 3] = 140376378875728 140376378867136julia> 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.933353julia> 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 12julia> a[2,1] # comma to separate the dimensions5
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 3julia> a[[1,3],1] # with a vector of positions in the first dimension2-element Vector{Int64}: 1 9julia> 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
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 0julia> a[b] # always flatted array returned (need eventually reshaping, see later)7-element Vector{Int64}: 1 5 9 6 3 7 11
Functionality related to dimensions
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)2julia> reshape(a, 2,3,2)2×3×2 Array{Int64, 3}: [:, :, 1] = 1 9 6 5 2 10 [:, :, 2] = 3 11 8 7 4 12julia> 2*3*2 == length(a)truejulia> 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.4652015053812224julia> 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.465202julia> permutedims(a) # "swap" the dimensions4×3 Matrix{Int64}: 1 5 9 2 6 10 3 7 11 4 8 12julia> reshape(a,4,3) # keep the column mayor order4×3 Matrix{Int64}: 1 6 11 5 10 4 9 3 8 2 7 12julia> 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 24julia> 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 6julia> 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 4julia> vec(a) # shadow copy (different view of the underlying data)4-element Vector{Int64}: 1 3 2 4julia> reshape(a,4) # shadow copy4-element Vector{Int64}: 1 3 2 4julia> a[:] # allocate, as all slice operations do4-element Vector{Int64}: 1 3 2 4
Other functionality related to Arrays
julia> vcat([1 2; 3 4], [5 6; 7 8]) # works also for DataFrames4×2 Matrix{Int64}: 1 2 3 4 5 6 7 8julia> hcat([1,2,3],[4,5,6]) # works also for DataFrames3×2 Matrix{Int64}: 1 4 2 5 3 6julia> a = [1 2; 3 4]2×2 Matrix{Int64}: 1 2 3 4julia> b = similar(a) # garbage inside2×2 Matrix{Int64}: 14 0 0 0julia> 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 200julia> idx = sortperm(a[:,3], rev=true) # return the positions that sort the 3rd column3-element Vector{Int64}: 2 3 1julia> 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 300julia> 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 2000julia> 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 300julia> 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 LinearAlgebrajulia> a = [-1,2,3]3-element Vector{Int64}: -1 2 3julia> b = [4,5,6]3-element Vector{Int64}: 4 5 6julia> transpose(a)1×3 transpose(::Vector{Int64}) with eltype Int64: -1 2 3julia> a'1×3 adjoint(::Vector{Int64}) with eltype Int64: -1 2 3julia> norm(a) # l-2 by default3.7416573867739413julia> norm(a,1)6.0
Vector products:
julia> dot(a,b) # dot, aka "inner" product24julia> a' * b == dot(a,b)truejulia> cross(a,b) # cross product3-element Vector{Int64}: -3 18 -13julia> a .* b # element-wise product3-element Vector{Int64}: -4 10 18julia> a * b'3×3 Matrix{Int64}: -4 -5 -6 8 10 12 12 15 18julia> A = [1 2 3; 6 4 5; 7 8 9]3×3 Matrix{Int64}: 1 2 3 6 4 5 7 8 9julia> A^(-1) # inverse3×3 Matrix{Float64}: -0.222222 0.333333 -0.111111 -1.05556 -0.666667 0.722222 1.11111 0.333333 -0.444444julia> A^23×3 Matrix{Int64}: 34 34 40 65 68 83 118 118 142julia> det(A) # determinant18.000000000000004julia> transpose(A)3×3 transpose(::Matrix{Int64}) with eltype Int64: 1 6 7 2 4 8 3 5 9julia> A'3×3 adjoint(::Matrix{Int64}) with eltype Int64: 1 6 7 2 4 8 3 5 9
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 9julia> I # operator that automatically scale to the context without actually building the matrixLinearAlgebra.UniformScaling{Bool} true*Ijulia> A*I3×3 Matrix{Int64}: 1 2 3 6 4 5 7 8 9julia> B = [1 2; 3 4]; B*I2×2 Matrix{Int64}: 1 2 3 4julia> (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 taught 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 3julia> t = (v...,) # note the comma(1, 2, 3)julia> v2 = [t...]3-element Vector{Int64}: 1 2 3julia> v3 = [i[1] for i in t]3-element Vector{Int64}: 1 2 3julia> v4 = collect(t)3-element Vector{Int64}: 1 2 3julia> v == v2 == v3 == v4true
Tuples with a variable number of same-type elements
While the tuple type usually includes information about each type of element, we may want to have a way to "summarise" this information by specifying that a certain number of elements all have the same type.This is the task of the Vararg argument that must be specified as the last parameters of a Tuple declaration. Vararg{T} allows for a variable number of elements, and Vararg{T,N} specifies an exact number of elements:
julia> typeof(("aaa",1,10)) <: Tuple{String,Vararg{Int}}truejulia> typeof(("aaa",1,10)) <: Tuple{String,Vararg{Int,2}}truejulia> typeof(("aaa",1,10)) <: Tuple{String,Vararg{Int,3}}false
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]1julia> nt.a1julia> 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
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 :cjulia> v = [1,2,3]3-element Vector{Int64}: 1 2 3julia> 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 3julia> v3 = [i[1] for i in nt]3-element Vector{Int64}: 1 2 3julia> v4 = collect(nt)3-element Vector{Int64}: 1 2 3julia> v == v2 == v3 == v4true
Dictionaries - Dict{Tkey,TValue}
Dictionary are mutable, key-referenced containers:
| Mutable | Immutable | |
|---|---|---|
| Use position | Arrays | Tuples |
| Use keys | Dictionaries | Named tuples |
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!1julia> get(mydict,'d',0) # specific a default if key not found0
Adding/deleting/checking
julia> mydict['d'] = 44julia> delete!(mydict,'d')Dict{Char, Int64} with 3 entries: 'a' => 1 'c' => 3 'b' => 2julia> haskey(mydict, 'a')truejulia> in(('a' => 1), mydict)truejulia> 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 6julia> mydictDict{Char, Int64} with 6 entries: 'f' => 5 'g' => 6 'a' => 1 'c' => 3 'e' => 4 'b' => 2julia> k = [:a,:b,:c]3-element Vector{Symbol}: :a :b :cjulia> v = [1,2,3]3-element Vector{Int64}: 1 2 3julia> 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 :cjulia> 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 1julia> sSet{Int64} with 4 elements: 4 2 3 1julia> push!(s,5)Set{Int64} with 5 elements: 5 4 2 3 1julia> delete!(s,1)Set{Int64} with 4 elements: 5 4 2 3julia> s2 = Set([4,5,6,7])Set{Int64} with 4 elements: 5 4 6 7julia> intersect(s,s2)Set{Int64} with 2 elements: 5 4julia> union(s,s2)Set{Int64} with 6 elements: 5 4 6 7 2 3julia> 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-09-22julia> nowTime = now()2024-09-22T16:37:23.734julia> typeof(todayDate)Dates.Datejulia> typeof(nowTime)Dates.DateTimejulia> Date <: Dates.AbstractTimetruejulia> DateTime <: Dates.AbstractTimetruejulia> nowTimeUnix = time() # The so-called "Unix time, a 64bit integer counting the number of seconds since the beginning of the year 19701.727023043765689e9julia> nowTime = Dates.unix2datetime(nowTimeUnix) # attention this is not local but UTC (Coordinated Universal Time - the Greenwitch time )!2024-09-22T16:37:23.765julia> nowTime = Dates.now(Dates.UTC) # an other way to have UTC time2024-09-22T16:37:23.766
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-25julia> newYearDay = Date("2031/01/01", "yyyy/m/d")2031-01-01julia> christmasLunch = DateTime("2030-12-25T12:30:00", ISODateTimeFormat) # well known string datetime ISO8601 Format2030-12-25T12:30:00julia> newYearEvenDinner = DateTime("Sat, 30 Dec 2030 21:30:00", RFC1123Format) # an othe well known format2030-12-30T21:30:00
Date and time formatters:
yYear digit (ef yyyy => 2030, yy => 30)mMonth digit (eg m => 3, mm => 03)uMonth name (eg "Jan")UMonth name long (eg "January")eDay of week (eg "Tue")EDay of week long (eg "Tuesday")dDay of month (eg d => 3, dd => 03)HHour digit (eg H => 8, HH => 08)pAM/PM specifier (eg "AM") (since Julia v1.3)MMinute digit (eg M => 0, MM => 00)SSecond digit (eg S => 0, SS => 00)sMillisecond 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-01julia> dt = DateTime(2030, 12, 31, 9, 30, 0, 0)2030-12-31T09:30:00
Date/Time extraction of information ("output")...
To String representation...
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)2030julia> isleapyear(christmasDay)falsejulia> month(christmasLunch)12julia> monthname(christmasDay)"December"julia> day(christmasDay)25julia> dayofweek(christmasDay)3julia> dayname(christmasDay)"Wednesday"julia> daysofweekinmonth(christmasDay) # there are 4 Wednesdays in December 20304julia> dayofweekofmonth(christmasDay) # and the 25th is the 4th of them4
- Only datetime..
julia> hour(christmasLunch)12julia> minute(christmasLunch)30julia> second(christmasLunch)0
Periods and datetime arithmetics
julia> hollidayPeriod = newYearDay - christmasDay # between dates is in days7 daysjulia> longPeriod = Date(2035,6,1) - christmasDay1619 daysjulia> mealPeriod = DateTime(2030,12,31,23,30) - newYearEvenDinner # between datetime is in milliseconds # newYearDay - newYearEvenDinner # error! no mixed93600000 millisecondsjulia> convert(DateTime,newYearDay)2031-01-01T00:00:00julia> convert(Date,newYearEvenDinner) # possible information loss2030-12-30julia> mealPeriod = convert(DateTime,newYearDay) - newYearEvenDinner95400000 millisecondsjulia> typeof(hollidayPeriod)Dates.Dayjulia> typeof(mealPeriod)Dates.Millisecond
Period hierarchy:
PeriodDatePeriodYearMonthWeekDay
TimePeriodHourMinuteSecondMillisecondMicrosecondNanosecond
julia> # convert(Dates.Year,longPeriod) # going up: error or inexacterror convert(Dates.Millisecond,longPeriod) # going down: fine139881600000 millisecondsjulia> convert(Dates.Millisecond,mealPeriod)95400000 millisecondsjulia> canLongPeriod = Dates.canonicalize(longPeriod)231 weeks, 2 daysjulia> 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-25julia> christmasPresentsOpeningTime = christmasLunch + Hour(3)2030-12-25T15:30:00julia> thisWeekdayNextCentury = dayname(today()+Year(100))"Friday"
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 until some condition is true
julia> sundayBefChristmas = toprev(d -> Dates.dayname(d) == "Sunday", christmasDay)2030-12-22julia> lastDayOfThisMonth = tonext(d -> Dates.day(d+Day(1)) == 1, today())2024-09-30
Find first or last weekday of {month,year} of a given date:
julia> lastTuesdayOfThisMonth = tolast(today(), 2, of=Month) # "2" stands for Tuesday2024-09-24julia> firstSundayOfThisYear = tofirst(today(), 7, of=Year) # "7" stands for Sunday2024-01-07
This page was generated using Literate.jl.