Categories: Julia

Sets and Dictionaries in Julia

In the past week, we’ve covered the basics of Julia, as well as looked at all the primitive types’ implementations. Today we’ll wind up the week with a brief discussion of the modern types in Julia

Dictionaries

We saw our first julian dictionary early on in the article on Looping in an example of for loop. As promised, here’s a more complete exposition on dictionaries. First of all, the syntax is slightly different:

julia> dict=Dict("machine"=>1,"geek"=>3,"learning"=>2,"geek"=>"awesome")
Dict{String,Any} with 3 entries:
  "geek"     => "awesome"
  "machine"  => 1
  "learning" => 2

The use of => for associative arrays was initiated by Perl, where the reason was to make key-value association clearer. Moreover, in Julia too, dictionaries are hashable, hence, the compiler can cache them.

One might wonder though, why not use -> like WolframLanguage and Scala ? The reason is that keeping in with the mathematical notation, Julia uses that token for maps as we’ll see in the last section today. Thus, one can read the dictionary as a tuple of associations( indicated by token that looks like the mathematical symbol for implication sign ). You access the value associated with a key just like in python:

julia> dict["geek"]
"awesome"

Or you can retrieve a value, while checking if it’s there (similar to how you’d use the get property in Python):

julia> get(dict,"MLG","got no value yet")
"got no value yet"

Note that the above won’t mutate the dictionary dict. If you want check if a key is there in the dictionary, and if absent, associate the default value to that key, you’d use get!:

julia> dict
Dict{String,Any} with 3 entries:
  "geek"     => "awesome"
  "machine"  => 1
  "learning" => 2

julia> get!(dict,"hey",-2)
-2

julia> dict
Dict{String,Any} with 4 entries:
  "geek"     => "awesome"
  "hey"      => -2
  "machine"  => 1
  "learning" => 2

Assigning values is similar to python as well:

julia> dict["hi"]=-1
-1

julia> dict
Dict{String,Any} with 5 entries:
  "geek"     => "awesome"
  "hi"       => -1
  "hey"      => -2
  "machine"  => 1
  "learning" => 2

As you may have guessed, you may also specify the type of a dictionary

julia> typedDict=Dict{Int,String}()
Dict{Int64,String}()

julia> typedDict[0]="MLG"
"MLG"

julia> typedDict["MLG"]=1 #This will give an error due to type issues
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Int64
Closest candidates are:
  convert(::Type{T}, ::T) where T<:Number at number.jl:6
  convert(::Type{T}, ::Number) where T<:Number at number.jl:7
  convert(::Type{T}, ::Ptr) where T<:Integer at pointer.jl:23
  ...
Stacktrace:
 [1] setindex!(::Dict{Int64,String}, ::Int64, ::String) at ./dict.jl:372
 [2] top-level scope at REPL[15]:1

On that note, remember that one you initialize a dictionary without specifying the types, Julia infers the appropriate types, and they become fixed. For example, the first dictionary we declared earlier, now must have it’s keys to be of type String

julia> dict[1]="MLG"
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type String
...

Some other methods are demonstrated below:

julia> keytype(dict) #what type of keys are expected
String

julia> haskey(dict,"MLG") # does a given dictionary have the specified key
false

julia> delete!(dict,"hey") #delete a key if present, else do nothing
Dict{String,Any} with 4 entries:
  "geek"     => "awesome"
  "hi"       => -1
  "machine"  => 1
  "learning" => 2

julia> pop!(dict,"hi")
-1

julia> keys(dict) # lets one iterate over the keys
Base.KeySet for a Dict{String,Any} with 3 entries. Keys:
  "geek"
  "machine"
  "learning"

julia> values(dict) # lets one iterate over values
Base.ValueIterator for a Dict{String,Any} with 3 entries. Values:
  "awesome"
  1
  2

julia> pairs(dict) #lets one iterate over key value pairs
Dict{String,Any} with 3 entries:
  "geek"     => "awesome"
  "machine"  => 1
  "learning" => 2

You might have noticed that some functions have an exclamation mark. Though unenforced, this signifies that the function is changing the object passed into it. We’ll talk more about this in an upcoming article devoted to functions.

Set

Sets in julia are implemented as instances of Base.Set. We can construct an empty set as:

julia> ϕ=Set()
Set{Any}()

Or use other objects to create sets:

julia> sa=Set([1 2 2]) #Directly creating a set of integers from an array
Set{Int64} with 2 elements:
  2
  1

julia> sm=Set([ 2 3 4; 5 6 7]) #Using a matrix to create a set of integers
Set{Int64} with 6 elements:
  7
  4
  2
  3
  5
  6

julia> sd=Set(dict) #Using a dictionary to create a set of tuples
Set{Pair{String,Any}} with 3 elements:
  Pair{String,Any}("learning", 2)
  Pair{String,Any}("geek", "awesome")
  Pair{String,Any}("machine", 1)

We can carry out set theoretic operations arbitrarily:

julia> union(sa,sm) #Union
Set{Int64} with 7 elements:
  7
  4
  2
  3
  5
  6
  1

julia> union(sa,sd) #Intersection
Set{Any} with 5 elements:
  Pair{String,Any}("learning", 2)
  2
  Pair{String,Any}("geek", "awesome")
  Pair{String,Any}("machine", 1)
  1

julia> intersect(sa,sd) #Intersection of sets of different type
Set{Int64}()

julia> setdiff(sm,sa) #Difference of sets
Set{Int64} with 5 elements:
  7
  4
  3
  5
  6

julia> symdiff(sd,sa) #Symmetric difference of sets
Set{Any} with 5 elements:
  Pair{String,Any}("learning", 2)
  2
  Pair{String,Any}("geek", "awesome")
  Pair{String,Any}("machine", 1)
  1

We can also have set theoretic conditions

julia> sa ⊆ sm
false

julia> issubset(sa,sm)
false

julia> sa ⊊ sm 
false

Note that ⊂ is not defined for sets in Julia.

To end the week, I implore you to read the documentation and find out how you would check if two sets are disjoint (Hint: first update to the latest version of Julia).

References

Editorial Staff

Recent Posts

MapReduce Algorithm

In this tutorial, we will focus on MapReduce Algorithm, its working, example, Word Count Problem,…

8 months ago

Linear Programming using Pyomo

Learn how to use Pyomo Packare to solve linear programming problems. In recent years, with…

1 year ago

Networking and Professional Development for Machine Learning Careers in the USA

In today's rapidly evolving technological landscape, machine learning has emerged as a transformative discipline, revolutionizing…

1 year ago

Predicting Employee Churn in Python

Analyze employee churn, Why employees are leaving the company, and How to predict, who will…

2 years ago

Airflow Operators

Airflow operators are core components of any workflow defined in airflow. The operator represents a…

2 years ago

MLOps Tutorial

Machine Learning Operations (MLOps) is a multi-disciplinary field that combines machine learning and software development…

2 years ago