{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Collections"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## In this lecture"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- [Introduction](#Introduction)\n",
    "- [Arrays](#Arrays)\n",
    "- [Tuples](#Tuples)\n",
    "- [Dictionaries](#Dictionaries)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Collections are groups of elements.  These elements are values of different Julia types.  Storing elements in collections is one of the most useful operations in computing."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Arrays"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Arrays are collections of values separated with commas and placed inside of a set of square brackets.  They can be represented in column or in row form."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3-element Array{Int64,1}:\n",
       " 1\n",
       " 2\n",
       " 3"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# A column vector\n",
    "array1 = [1, 2, 3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `typeof()` function shows that `array1` is an instance of an array object, containing integer values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Array{Int64,1}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# The type of the object array1\n",
    "typeof(array1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Below we create `array2`.  Note that there are only spaces between the elements."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1×3 Array{Int64,2}:\n",
       " 1  2  3"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# A row vector\n",
    "array2 = [1 2 3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `transpose()` function will create a linear algebra transpose of our column vector, `array1`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1×3 LinearAlgebra.Transpose{Int64,Array{Int64,1}}:\n",
       " 1  2  3"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# The transpose\n",
    "transpose(array1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When the types of the elemnts are not the same, all elements _inherit_ the _highest_ type."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3-element Array{Float64,1}:\n",
       " 1.0\n",
       " 2.0\n",
       " 3.0"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# With a mix of types, all the elements inherent the \"highest\" type\n",
    "array2 = [1, 2, 3.0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Index for one of the original integers will be Float64\n",
    "array2[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Arrays can have more than one _dimension_ (here dimension does not refer to the number of elements in a vector, representing a vector field)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×3 Array{Int64,2}:\n",
       " 1  4  7\n",
       " 2  5  8\n",
       " 3  6  9"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Column-wise entry of multidimensional array\n",
    "array3 = [[1, 2, 3] [4, 5, 6] [7, 8, 9]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×3 Array{Int64,2}:\n",
       " 1  2  3\n",
       " 4  5  6\n",
       " 7  8  9"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Row-wise entry of multidimensional array\n",
    "array4 = [[1 2 3]; [4 5 6]; [7 8 9]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `length()` function returns the number of elements."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Length of array3\n",
    "length(array3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "length(array4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since the two arrays above were created differently, let's take a look at indices of there elements."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Element 1 is 1\n",
      "Element 2 is 2\n",
      "Element 3 is 3\n",
      "Element 4 is 4\n",
      "Element 5 is 5\n",
      "Element 6 is 6\n",
      "Element 7 is 7\n",
      "Element 8 is 8\n",
      "Element 9 is 9\n"
     ]
    }
   ],
   "source": [
    "# Index order of column-wise array\n",
    "for i in 1:length(array3)\n",
    "    println(\"Element $(i) is \", array3[i])\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Element 1 is 1\n",
      "Element 2 is 4\n",
      "Element 3 is 7\n",
      "Element 4 is 2\n",
      "Element 5 is 5\n",
      "Element 6 is 8\n",
      "Element 7 is 3\n",
      "Element 8 is 6\n",
      "Element 9 is 9\n"
     ]
    }
   ],
   "source": [
    "# Index order of row-wise array\n",
    "for i in 1:length(array4)\n",
    "    println(\"Element $(i) is \", array4[i])\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Elements can be repeated using the `repeat()` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6-element Array{Int64,1}:\n",
       " 1\n",
       " 2\n",
       " 1\n",
       " 2\n",
       " 1\n",
       " 2"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Using repeat() to repeat column elements\n",
    "repeat([1, 2], 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×2 Array{Int64,2}:\n",
       " 1  2\n",
       " 1  2\n",
       " 1  2"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Using repeat() to repeat row elements\n",
    "repeat([1 2], 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `range()` function ccreates a range object.  The first argument is the value of the first element.  The `step = ` argument specifies the stepsize, and the `length =` argument specifies how many elements the array should have."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1:1:10"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Using range(start, step, number of elements)\n",
    "range(1, step = 1, length = 10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can change the range object into an array using the `collect()` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10-element Array{Int64,1}:\n",
       "  1\n",
       "  2\n",
       "  3\n",
       "  4\n",
       "  5\n",
       "  6\n",
       "  7\n",
       "  8\n",
       "  9\n",
       " 10"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create collections using the collect() function\n",
    "collect(range(1, step = 1, length = 10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10-element Array{Int64,1}:\n",
       "  1\n",
       "  2\n",
       "  3\n",
       "  4\n",
       "  5\n",
       "  6\n",
       "  7\n",
       "  8\n",
       "  9\n",
       " 10"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Short-hand syntax\n",
    "collect(1:10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can create empty arrays as placeholders."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2×3 Array{Union{Missing, Int64},2}:\n",
       " missing  missing  missing\n",
       " missing  missing  missing"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Creating empty array with two rows and three columns\n",
    "array5 = Array{Union{Missing, Int}}(missing, 2, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Reshaping is achieved using the `reshape()` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×2 reshape(::Array{Union{Missing, Int64},2}, 3, 2) with eltype Union{Missing, Int64}:\n",
       " missing  missing\n",
       " missing  missing\n",
       " missing  missing"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Reshaping\n",
    "reshape(array5, 3, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Every element in an arrays has an index (address) value.  We already saw this above when we created a for-loop to cycle through the values of our row vs. column created arrays."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10×5 Array{Int64,2}:\n",
       " 20  12  11  13  18\n",
       " 10  17  10  15  19\n",
       " 16  13  11  11  13\n",
       " 10  17  17  11  17\n",
       " 16  20  17  13  13\n",
       " 15  11  15  20  20\n",
       " 20  17  20  19  20\n",
       " 10  10  19  15  17\n",
       " 13  14  10  10  20\n",
       " 15  18  18  10  13"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Creating a 10 x 5 array with each element drawn randomly from value 10 through 20\n",
    "array6 = rand(10:20, 10, 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Indexing is indicated with square brackets.  For arrays with rows and columns, the index values will be in the form `[row, column]`.  A colon serves as short-hand syntax indicating _all_ values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10-element Array{Int64,1}:\n",
       " 20\n",
       " 10\n",
       " 16\n",
       " 10\n",
       " 16\n",
       " 15\n",
       " 20\n",
       " 10\n",
       " 13\n",
       " 15"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#A ll rows in first column\n",
    "array6[:, 1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4-element Array{Int64,1}:\n",
       " 17\n",
       " 13\n",
       " 17\n",
       " 20"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Rows two through five of second column\n",
    "array6[2:5, 2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×2 Array{Int64,2}:\n",
       " 10  19\n",
       " 10  17\n",
       " 15  20"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Values in rows 2, 4, 6, and in columns 1 and 5\n",
    "array6[[2, 4, 6], [1, 5]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3-element Array{Int64,1}:\n",
       " 11\n",
       " 13\n",
       " 18"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Values in row 1 from column 3 to the last column\n",
    "array6[1, 3:end]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Boolean logic can be used to select values based on rules.  Below we check if each value in column one is equal to or greater than $12$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10-element BitArray{1}:\n",
       " 1\n",
       " 0\n",
       " 1\n",
       " 0\n",
       " 1\n",
       " 1\n",
       " 1\n",
       " 0\n",
       " 1\n",
       " 1"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Boolean logic (returning only true and false)\n",
    "array6[:, 1] .> 12"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can add values to an array using the `push!()` function.  Many functions in Julia have an added exclamation mark, called a _bang_.  It is used to make permanent changes to the values in a computer variable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6-element Array{Int64,1}:\n",
       "  1\n",
       "  2\n",
       "  3\n",
       "  4\n",
       "  5\n",
       " 10"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Creating a five element array\n",
    "array7 = [1, 2, 3, 4, 5]\n",
    "# Permanantly append 10 to end of array\n",
    "push!(array7, 10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `pop!()` function removes the last element (the bang makes it permanent)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pop!(array7)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also change the value of an element by using its index."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1000"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Change second element value to 1000\n",
    "array7[2] = 1000"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5-element Array{Int64,1}:\n",
       "    1\n",
       " 1000\n",
       "    3\n",
       "    4\n",
       "    5"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Viewing the change\n",
    "array7"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "_List comprehension_ is a term that refers to the creating of an array using a _recipe_.  View the following example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5-element Array{Int64,1}:\n",
       "  3\n",
       "  6\n",
       "  9\n",
       " 12\n",
       " 15"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# An example of list comprehension\n",
    "array8 = [3 * i for i in 1:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The Julia syntax is very expressive, as the above example shows.  Square brackets indicate that we are creating a list.  The exprssion, `3 * i` indicates what we want each element to look like.  The for-loop uses the palceholder over which we wish to iterate, together with the range that we require."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This allows for very complex array creation, which makes it quite versatile."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×3 Array{Int64,2}:\n",
       " 1  2  3\n",
       " 2  4  6\n",
       " 3  6  9"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Column-wise collection iterating through second element first\n",
    "array9 = [a * b for a in 1:3, b in 1:3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Arithmetic operations on arrays are performed through the process of _broadcasting_.  Below we add $1$ to each element in `array8`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5-element Array{Int64,1}:\n",
       "  4\n",
       "  7\n",
       " 10\n",
       " 13\n",
       " 16"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Elementwise addition of a scalar using dot notation\n",
    "array8 .+ 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When arrays are of similar shape, we can do elemnt wise addition."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5-element Array{Int64,1}:\n",
       "    4\n",
       " 1006\n",
       "   12\n",
       "   16\n",
       "   20"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Elementwise addition of similar sized arrays\n",
    "array7 + array8"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "While it is nice to have a complete set of elemnts, data is often _missing_.  Missing is a Julia data type that provides a placeholder for missing data in a statistical sense.  It propagates automatically and its equality as a type can be tested.  Sorting is possible since missing is seen as greater than other values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "missing"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Propagation\n",
    "missing + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "missing"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "missing > 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5-element Array{Union{Missing, Int64},1}:\n",
       " 11       \n",
       " 22       \n",
       " 33       \n",
       "   missing\n",
       " 55       "
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[1, 2, 3, missing, 5] + [10, 20, 30, 40 ,50]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "missing"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Checking equality of value using ==\n",
    "# Cannot return true or false since value is not known\n",
    "missing == missing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Checking equality of type with ===\n",
    "missing === missing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Checking type equality with isequal()\n",
    "isequal(missing, missing)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Sorting with isless()\n",
    "isless(1, missing)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Checking on infinity\n",
    "isless(Inf, missing)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can create an array of zeros."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×3 Array{Int8,2}:\n",
       " 0  0  0\n",
       " 0  0  0\n",
       " 0  0  0"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# A 3 x 3 array of integer zeros\n",
    "array11 = zeros(Int8, 3, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here is an array of ones."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×3 Array{Float16,2}:\n",
       " 1.0  1.0  1.0\n",
       " 1.0  1.0  1.0\n",
       " 1.0  1.0  1.0"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# A 3 x 3 array of floating point ones\n",
    "array12 = ones(Float16, 3, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Boolean values are also allowed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×3 BitArray{2}:\n",
       " 1  1  1\n",
       " 1  1  1\n",
       " 1  1  1"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Array of true (bit array) values\n",
    "array13 = trues(3, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can even fill an array with a specified value."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×3 Array{Int64,2}:\n",
       " 10  10  10\n",
       " 10  10  10\n",
       " 10  10  10"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Fill an array with elements of value x\n",
    "array14 = fill(10, 3, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We have already seen that elemnts of different types all inherit the _highest_ type.  We can in fact, change the type manually, with the convert function.  As elsewhere in Julia, the dot opetaror maps the function to each element of a list."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×3 Array{Float16,2}:\n",
       " 10.0  10.0  10.0\n",
       " 10.0  10.0  10.0\n",
       " 10.0  10.0  10.0"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Convert elements to a different data type\n",
    "convert.(Float16, array14)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Arrays can be concatenated."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6-element Array{Int64,1}:\n",
       "  1\n",
       "  2\n",
       "  3\n",
       " 10\n",
       " 20\n",
       " 30"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Concatenate arrays along rows (makes rows)\n",
    "array15 = [1, 2, 3]\n",
    "array16 = [10, 20, 30]\n",
    "cat(array15, array16, dims = 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6-element Array{Int64,1}:\n",
       "  1\n",
       "  2\n",
       "  3\n",
       " 10\n",
       " 20\n",
       " 30"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Same as above\n",
    "vcat(array15, array16)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×2 Array{Int64,2}:\n",
       " 1  10\n",
       " 2  20\n",
       " 3  30"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Concatenate arrays along columns (makes columns)\n",
    "cat(array15, array16, dims = 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×2 Array{Int64,2}:\n",
       " 1  10\n",
       " 2  20\n",
       " 3  30"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Same as above\n",
    "hcat(array15, array16)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tuples"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tuples are immutable collections.  Immutable refers to the fact that the values are set and cannot be changed.  This type is indicated by the use of parenthesis instead of square brackets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 2, 3, 4, \"Julia\")"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Tuples with mixed types\n",
    "tuple1 = (1, 2, 3, 4, \"Julia\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's check on the values and types of each element."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " The value of the tuple at index number 1 is 1 and the type is Int64.\n",
      " The value of the tuple at index number 2 is 2 and the type is Int64.\n",
      " The value of the tuple at index number 3 is 3 and the type is Int64.\n",
      " The value of the tuple at index number 4 is 4 and the type is Int64.\n",
      " The value of the tuple at index number 5 is Julia and the type is String.\n"
     ]
    }
   ],
   "source": [
    "# For loop to look at value and type of each element\n",
    "for i in 1:length(tuple1)\n",
    "    println(\" The value of the tuple at index number $(i) is $(tuple1[i]) and the type is $(typeof(tuple1[i])).\")\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tuples are useful as each elemnt can be named."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Each element can be named\n",
    "a, b, c, seven = (1, 3, 5, 7)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seven"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A range can be used to reverse the order of a tuple."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(\"Julia\", 4, 3, 2, 1)"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Reverse order index (can be done with arrays too)\n",
    "tuple1[end:-1:1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Arrays can be made up of elemnts of different length."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((1, 2, 3), 1, 2, (3, 100, 1))"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Mixed length tuples\n",
    "tuple2 = ((1, 2, 3), 1, 2, (3, 100, 1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 100, 1)"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Element 4\n",
    "tuple2[4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Element 2 in element 4\n",
    "tuple2[4][2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dictionaries"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dictionaries are collection sof key-value pairs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Dict{Int64,Int64} with 3 entries:\n",
       "  2 => 66\n",
       "  3 => 1\n",
       "  1 => 77"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1 Example of a dictionary\n",
    "dictionary1 = Dict(1 => 77, 2 => 66, 3 => 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the example above we have key-values of `1,2,3` and value-values of `77,66,1`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Dict{Int64,Int64} with 3 entries:\n",
       "  2 => 200\n",
       "  3 => 300\n",
       "  1 => 100"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# The => is shorthand for the Pair() function\n",
    "dictionary2 = Dict(Pair(1,100), Pair(2,200), Pair(3,300))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can specify the types used in a dict."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Dict{Any,Any} with 3 entries:\n",
       "  2 => 66\n",
       "  3 => \"three\"\n",
       "  1 => 77"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2 Specifying types\n",
    "dictionary3 = Dict{Any, Any}(1 => 77, 2 => 66, 3 => \"three\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Dict{Any,Any} with 2 entries:\n",
       "  (2, 3) => \"hello\"\n",
       "  \"a\"    => 1"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# We can get a bit crazy\n",
    "dictionary4 = Dict{Any, Any}(\"a\" => 1, (2, 3) => \"hello\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is perhaps more useful to use symbols (colon symbol and a name) as key values.  We can then refer to the key-name when we want to inquire about its value."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "300"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Using symbols as keys\n",
    "dictionary5 = Dict(:A => 300, :B => 305, :C => 309)\n",
    "dictionary5[:A]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can check on the key-value pairs in a dictionary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Using in() to check on key-value pairs\n",
    "in((:A => 300), dictionary5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Change value using the key is easy to perform."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Dict{Symbol,Int64} with 3 entries:\n",
       "  :A => 300\n",
       "  :B => 305\n",
       "  :C => 1000"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Changing an existing value\n",
    "dictionary5[:C] = 1000\n",
    "dictionary5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `delete!()` function permanently deletes a key-value pair."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Dict{Symbol,Int64} with 2 entries:\n",
       "  :B => 305\n",
       "  :C => 1000"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Using the delete!() function\n",
    "delete!(dictionary5, :A)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can list both the keys and the values in a dictionary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Base.KeySet for a Dict{Symbol,Int64} with 2 entries. Keys:\n",
       "  :B\n",
       "  :C"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# The keys of a dictionary\n",
    "keys(dictionary5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Base.ValueIterator for a Dict{Symbol,Int64} with 2 entries. Values:\n",
       "  305\n",
       "  1000"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "values(dictionary5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Through the use of iteration, we can get create in the creation and interrogation of a dictionary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Creating a dictionary with automatic keys\n",
    "procedure_vals = [\"Appendectomy\", \"Colectomy\", \"Cholecystectomy\"]\n",
    "procedure_dict = Dict{AbstractString,AbstractString}()\n",
    "for (s, n) in enumerate(procedure_vals)\n",
    "    procedure_dict[\"x_$(s)\"] = n\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Dict{AbstractString,AbstractString} with 3 entries:\n",
       "  \"x_1\" => \"Appendectomy\"\n",
       "  \"x_2\" => \"Colectomy\"\n",
       "  \"x_3\" => \"Cholecystectomy\""
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "procedure_dict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x_1 is Appendectomy\n",
      "x_2 is Colectomy\n",
      "x_3 is Cholecystectomy\n"
     ]
    }
   ],
   "source": [
    "# Iterating through a dictionary by key and value\n",
    "for (k, v) in procedure_dict\n",
    "    println(k, \" is \",v)\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lastly, we can sort using iteration."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a is 1\n",
      "b is 2\n",
      "c is 3\n",
      "d is 4\n",
      "e is 5\n",
      "f is 6\n"
     ]
    }
   ],
   "source": [
    "# Sorting\n",
    "dictionary6 = Dict(\"a\"=> 1,\"b\"=>2 ,\"c\"=>3 ,\"d\"=>4 ,\"e\"=>5 ,\"f\"=>6)\n",
    "# Sorting using a for loop\n",
    "for k in sort(collect(keys(dictionary6)))\n",
    "    println(\"$(k) is $(dictionary6[k])\")\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3-element Array{Int64,1}:\n",
       " 1\n",
       " 2\n",
       " 3"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [[1, 2, 3] [4, 5, 6] ]\n",
    "b = [1,2,3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2-element Array{Int64,1}:\n",
       " 14\n",
       " 32"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "transpose(a) * b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2×3 LinearAlgebra.Transpose{Int64,Array{Int64,2}}:\n",
       " 1  2  3\n",
       " 4  5  6"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "transpose(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(6,)"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "size(repeat([1, 2], 3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Tuple{String,Int64,String,Int64,String,Int64}"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "typeof((\"A\", 3, \"B\", 4, \"C\", 2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Julia 1.2.0",
   "language": "julia",
   "name": "julia-1.2"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "1.2.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
