print and println@printftry-catch for Exception HandlingfinallyDictionaries provide a method to store and retrieve information using specific labels or identifiers, rather than numerical positions. This capability is essential in scenarios where data needs to be associated with unique descriptors. Dictionaries, often called maps, associative arrays, or hash tables in other programming languages, are collections that store data as key-value pairs.
Think of a dictionary: you look up a word (the unique) to find its definition (the value). Similarly, in a Julia dictionary, each unique key is associated with a specific value. This structure is incredibly useful for situations where you need to quickly find a value if you know its corresponding key.
Unlike arrays, which are ordered by numerical indices (in Julia, typically 1, 2, 3,...), dictionaries are generally considered unordered from the perspective of how you access data. You don't ask for "the third item" in a dictionary; you ask for "the value associated with this specific key." (It's worth noting that Julia's Dict type does preserve insertion order since Julia version 1.0, but the primary mode of interaction remains key-based lookup.)
You can create a dictionary in Julia using the Dict() constructor. You can create an empty dictionary or initialize it with key-value pairs. The "pair" operator => is used to link a key to its value.
Let's create an empty dictionary that can store keys and values of any type:
julia> scores = Dict()
Dict{Any, Any}()
This creates a dictionary where both keys and values can be of Any type, meaning they can hold data of various types.
Often, you'll want to be more specific about the types of keys and values your dictionary will hold. This can improve performance and help catch errors early by ensuring type consistency. For example, to create a dictionary where keys are strings (representing student names) and values are integers (their scores):
julia> student_scores = Dict{String, Int}()
Dict{String, Int64}()
Notice Julia infers Int64 for Int on a typical 64-bit system. Int64 is a specific type of integer that can store 64-bit numbers.
You can also initialize a dictionary with values directly when you create it:
julia> fruit_colors = Dict("apple" => "red", "banana" => "yellow", "grape" => "purple")
Dict{String, String} with 3 entries:
"banana" => "yellow"
"apple" => "red"
"grape" => "purple"
In this case, Julia infers that the keys are of type String and the values are also of type String based on the initial data provided. A critical property of dictionaries is that keys must be unique. If you try to add a duplicate key during initialization, the value associated with the last occurrence of that key will be used.
Once a dictionary is created, you can add new key-value pairs or modify the value associated with an existing key. This is done using square bracket notation [], similar to how you might access array elements, but you use the key instead of a numerical index.
To add a new entry to an existing dictionary:
julia> student_scores["Alice"] = 95
95
julia> student_scores["Bob"] = 88
88
julia> student_scores
Dict{String, Int64} with 2 entries:
"Bob" => 88
"Alice" => 95
If you assign a value to a key that already exists in the dictionary, Julia updates the value associated with that key. This is useful for changing data.
julia> student_scores["Alice"] = 97 # Alice improved her score!
97
julia> student_scores
Dict{String, Int64} with 2 entries:
"Bob" => 88
"Alice" => 97
To retrieve a value from a dictionary, you use its key within square brackets:
julia> alice_score = student_scores["Alice"]
97
If you attempt to access a key that doesn't exist in the dictionary, Julia will raise a KeyError. This type of error can stop your program if it's not handled.
julia> student_scores["Charlie"]
ERROR: KeyError: key "Charlie" not found
Stacktrace:
[1] getindex(h::Dict{String, Int64}, key::String)
@ Base ./dict.jl:499
[2] top-level scope
@ REPL[7]:1
To safely access values and avoid potential errors, you can first check if a key exists using the haskey() function:
julia> haskey(student_scores, "Bob")
true
julia> haskey(student_scores, "Charlie")
false
A more direct way to retrieve a value safely is by using the get() function. It takes three arguments: the dictionary, the key you're looking for, and a default value to return if the key is not found.
julia> charlie_score = get(student_scores, "Charlie", 0) # Return 0 if Charlie is not found
0
julia> alice_score_safe = get(student_scores, "Alice", 0) # Alice exists, so her score is returned
97
Using get() is often preferred because it combines the check and retrieval into a single, concise operation, making your code cleaner.
You can remove key-value pairs from a dictionary using functions like pop! or delete!.
The pop!(dictionary, key) function removes the key-value pair for the given key and returns the removed value. If the key is not found, it will throw a KeyError, similar to direct access.
julia> student_scores
Dict{String, Int64} with 2 entries:
"Bob" => 88
"Alice" => 97
julia> bobs_score = pop!(student_scores, "Bob")
88
julia> student_scores
Dict{String, Int64} with 1 entry:
"Alice" => 97
You can also provide a default value to pop!, which will be returned if the key isn't found, thus preventing an error:
julia> pop!(student_scores, "David", "Not Present") # David isn't in the dict
"Not Present"
The delete!(dictionary, key) function also removes the key-value pair. However, instead of returning the value, it returns the modified dictionary itself. It does not cause an error if the key is not found.
julia> student_scores["Carol"] = 92
92
julia> student_scores
Dict{String, Int64} with 2 entries:
"Carol" => 92
"Alice" => 97
julia> delete!(student_scores, "Alice")
Dict{String, Int64} with 1 entry:
"Carol" => 92
julia> student_scores
Dict{String, Int64} with 1 entry:
"Carol" => 92
It's common to need to process all entries in a dictionary. Julia provides several convenient ways to iterate through them using for loops.
You can iterate over key-value pairs directly. In each step of the loop, you get both the key and its corresponding value.
julia> fruit_colors = Dict("apple" => "red", "banana" => "yellow", "grape" => "purple")
Dict{String, String} with 3 entries:
"banana" => "yellow"
"apple" => "red"
"grape" => "purple"
julia> for (fruit, color) in fruit_colors
println("The color of $fruit is $color.")
end
The color of banana is yellow.
The color of apple is red.
The color of grape is purple.
If you only need to work with the keys, you can use the keys() function:
julia> for fruit in keys(fruit_colors)
println("$fruit is a known fruit.")
end
banana is a known fruit.
apple is a known fruit.
grape is a known fruit.
Similarly, if you only need the values, you can use the values() function:
julia> for color in values(fruit_colors)
println("We have a fruit with the color: $color.")
end
We have a fruit with the color: yellow.
We have a fruit with the color: red.
We have a fruit with the color: purple.
Both keys() and values() return iterators. Iterators are efficient structures that allow you to access elements one by one, typically without creating a new collection in memory.
Julia provides several other useful functions for working with dictionaries:
length(my_dict): Returns the number of key-value pairs in the dictionary.
julia> length(fruit_colors)
3
isempty(my_dict): Returns true if the dictionary has no entries, and false otherwise.
julia> isempty(fruit_colors)
false
julia> isempty(Dict()) # An empty dictionary
true
merge(dict1, dict2): Creates a new dictionary containing all key-value pairs from dict1 and dict2. If a key exists in both dictionaries, the value from dict2 (the second argument) is used in the new dictionary. The original dictionaries are not changed.
julia> dict_a = Dict("a" => 1, "b" => 2)
Dict{String, Int64} with 2 entries:
"b" => 2
"a" => 1
julia> dict_b = Dict("b" => 3, "c" => 4) # "b" also exists in dict_a
Dict{String, Int64} with 2 entries:
"b" => 3
"c" => 4
julia> merged_dict = merge(dict_a, dict_b)
Dict{String, Int64} with 3 entries:
"b" => 3 # Value from dict_b for key "b"
"c" => 4
"a" => 1
There is also a merge!(dict1, dict2) function (with an exclamation mark), which modifies dict1 in place by adding entries from dict2.Dictionaries are a fundamental data structure, particularly powerful in specific scenarios:
Dict("name" => "Julia", "version" => 1.9, "is_awesome" => true) can store various attributes of an entity.Compared to arrays, which are ordered sequences accessed by integer indices, dictionaries are (for access purposes) unordered collections accessed by keys that can be of various types (like strings, numbers, or symbols). If the order of elements is important and you typically access them sequentially or by their numerical position, an array is usually the better choice. If, however, you need to associate unique keys with values for quick and direct retrieval based on those keys, a dictionary is more suitable.
Let's illustrate a common use case: counting word frequencies in a list of words. Suppose we have a list (an array) of words:
julia> words = ["hello", "hello", "julia", "hello"]
6-element Vector{String}:
"hello"
""
"hello"
"julia"
""
"hello"
julia> word_counts = Dict{String, Int}() # Create an empty dictionary for counts
Dict{String, Int64}()
julia> for word in words
# If 'word' is already a key, get its count. Otherwise, default to 0.
# Then, add 1 to this count and update the dictionary.
word_counts[word] = get(word_counts, word, 0) + 1
end
julia> word_counts
Dict{String, Int64} with 3 entries:
"julia" => 1
"global" => 2
"hello" => 3
In this example, the get(word_counts, word, 0) part is important. It safely retrieves the current count of a word. If the word is encountered for the first time (and thus not yet in word_counts), get returns the default value 0. We then add 1 to this count and store it back in the dictionary using word as the key. This is a common and efficient pattern for using dictionaries to tally items.
The diagram below shows a simple representation of a dictionary:
Each entry in a dictionary consists of a distinct key linked to its corresponding value. Accessing a value is done through its key, not by its position.
Dictionaries provide a flexible and efficient way to manage labeled data. As you continue your programming with Julia, you'll find them to be an indispensable tool for a wide range of tasks, from simple data storage to forming parts of more complex algorithms. They effectively complement arrays and tuples by offering a different, key-based approach to structuring and accessing your collections of information.
Was this section helpful?
© 2026 ApX Machine LearningEngineered with