# Introducing Julia/Dictionaries and sets
## Dictionaries

Many of the functions introduced so far have been shown working on arrays (and tuples). But arrays are just one type of collection. Julia has others.
A simple look-up table is a useful way of organizing many types of data: given a single piece of information, such as a number, string, or symbol, called the key, what is the corresponding data value? For this purpose, Julia provides the Dictionary object, called Dict for short. It's an "associative collection" because it associates keys with values.

### Creating dictionaries

You can create a simple dictionary using the following syntax:
dict is now a dictionary. The keys are "a", "b", and "c", the corresponding values are 1, 2, and 3. The => operator is called the Pair function. In a dictionary, keys are always unique – you can't have two keys with the same name.
If you know the types of the keys and values in advance, you can (and probably should) specify them after the Dict keyword, in curly braces:
You can also create dictionaries using the generator/comprehensions syntax:
Use the following syntax to create a typed empty dictionary:
or you can omit the types, and get an untyped dictionary:
It's sometimes useful to create dictionary entries using a for loop:
This is one way you could create a set of 'variables' stored in a dictionary:

### Looking things up

To get a value, if you have the key:
if the keys are strings. Or, if the keys are symbols:
Or if the keys are integers:
You can instead use the get function, and provide a fail-safe default value if there's no value for that particular key:
If you don't want get to provide a default value, use a try...catch block:
To change a value assigned to an existing key (or assign a value to a hitherto unseen key):

#### Keys

Keys must be unique for a dictionary. There's always only one key called a in this dictionary, so when you assign a value to a key that already exists, you're not creating a new one, just modifying an existing one.
To see if the dictionary contains a key, use haskey:
To check for the existence of a key/value pair:
To add a new key and value to a dictionary, use this:
You can delete a key from the dictionary, using delete!:
You'll notice that the dictionary doesn't seem to be sorted in any way — at least, the keys are in no particular order. This is due to the way they're stored, and you can't sort them in place. (But see Sorting, below.)
To get all keys, use the keys function:
The result is an iterator that has just one job: to iterate through a dictionary key by key:
This uses the list comprehension form ([ new-element for loop-variable in iterator ]) and each new element is collected into an array. An alternative would be:

#### Values

To retrieve all the values, use the values function:
If you want to go through a dictionary and process each key/value, you can make use the fact that dictionaries themselves are iterable objects:
where kv is a tuple containing each key/value pair in turn.
Or you could do:
Even better, you can use a key/value tuple to simplify the iteration even more:
Here's another example:
(Notice the string interpolation operator, $. This allows you to use a variable's name in a string and get the variable's value when the string is printed. You can include any Julia expression in a string using $.)

### Sorting a dictionary

Because dictionaries don't store the keys in any particular order, you might want to output the dictionary to a sorted array to obtain the items in order:
If you really need to have a dictionary that remains sorted all the time, you can use the SortedDict data type from the DataStructures.jl package (after having installed it).
Recent versions of Julia sort dictionaries for you:

### Simple example: counting words

A simple application of a dictionary is to count how many times each word appears in a piece of text. Each word is a key, and the value of the key is the number of times that word appears in the text.
Let's count the words in the Sherlock Holmes stories. I've downloaded the text from the excellent Project Gutenberg and stored them in a file "sherlock-holmes-canon.txt". To create a list of words from the loaded text in canon, we'll split the text using a regular expression, and convert every word to lowercase. (There are probably faster methods.)
wordlist is now an array of nearly 700,000 words:
To store the words and the word counts, we'll create a dictionary:
To build the dictionary, loop through the list of words, and use get to look up the current tally, if any. If the word has already been seen, the count can be increased. If the word hasn't been seen before, the fall-back third argument of get ensures that the absence doesn't cause an error, and 1 is stored instead.
Now you can look up words in the wordcounts dictionary and find out how many times they appear:
Dictionaries aren't sorted, but you can use the collect and keys functions on the dictionary to collect the keys and then sort them. In a loop you can work through the dictionary in alphabetical order:
But how do you find out the most common words? One way is to use collect to convert the dictionary to an array of tuples, and then to sort the array by looking at the last value of each tuple:
To see only the top 20 words:
In a similar way, you can use the filter function to find, for example, all words that start with "k" and occur less than four times:

### More complex structures

A dictionary can hold many different types of values. Here for example is a dictionary where the keys are strings and the values are arrays of arrays of points (assuming that the Point type has been defined already). For example, this could be used to store graphical shapes describing the letters of the alphabet (some of which have two or more loops):
Or create a dictionary with some already-known values:
Add another array to the first one:

## Sets

A set is a collection of elements, just like an array or dictionary, with no duplicated elements.
The two important differences between a set and other types of collection is that in a set you can have only one of each element, and, in a set, the order of elements isn't important (whereas an array can have multiple copies of an element and their order is remembered).
You can create an empty set using the Set constructor function:
As elsewhere in Julia, you can specify the type:
You can create and fill sets in one go:
or you can let Julia "guess the type":
Quite a few of the functions that work with arrays also work with sets. Adding elements to sets, for example, is a bit like adding elements to arrays. You can use push!:
But you can't use pushfirst!, because that works only for things that have a concept of "first", like arrays.
What happens if you try to add something to the set that's already there? Absolutely nothing. You don't get a copy added, because it's a set, not an array, and sets don't store repeated elements.
To see if something is in the set, you can use in:
There are some standard operations you can do with sets, namely find their union, intersection, and difference, with the functions, union, intersect, and setdiff:
The union of two sets is the set of everything that is in one or the other sets. The result is another set – so you can't have two "yellow"s here, even though we've got a "yellow" in each set:
The intersection of two sets is the set that contains every element that belongs to both sets:
The difference between two sets is the set of elements that are in the first set, but not in the second. This time, the order in which you supply the sets matters. The setdiff function finds the elements that are in the first set, colors, but not in the second set, rainbow:

## Other functions

Functions that work on arrays and sets sometimes work on dictionaries and other collections too. For example, some of the set operations can be applied to dictionaries, not just sets and arrays:
Notice that the results are returned as arrays of Pairs, rather than as Dictionaries.
Functions such as filter, map, and collect which we've already seen being used with arrays also work with dictionaries:
There's a merge function which can merge two dictionaries:
The findmin function can find the minimum value in a dictionary, and return the value, and its key.