Dictionaries

Dictionaries are Pythons associate arrays or maps, which implements by using hash tables. Dictionaries access values by means of integers, strings or other Python Objects called keys. Dictionaries can store objects of any type. Values in dictionaries are not implicity ordered relative to one another because dictionary keys are'nt just numbers. If orering is import then you can use a ordered dictionary which can be imported from the Collections module.

Creating
empty = {}                         # create an empty dictionary
          
fruit = {"orange": "a sweet, orange, citrus fruit",
         "apple": "good for making cider",
         "lemon": "a sour, yellow citrus fruit",
         "grape": "a small, sweet fruit growing in bunches",
         "lime": "a sour, green citrus fruit",
         "smelly fruit": "horrible smelly fruit"}
         
print(fruit['orange'])
get length
sports = { "outdoor": "football", "indoor": "squash", "underground": "caving" }
len(sports)
get keys and values and both
fruit.keys()                         # returns all keys
fruit.values()                       # returns all values
fruit.items()                        # returns both keys and values

fruit.get('orange')                  # return value associated with key 'orange'
fruit.get('banana', 'No Banana')     # if no banana key is found, return string 'No Banana'

Searching
'orange' in fruit                    # True
'banana' in fruit                    # False
Deleting
del(fruit['orange'])
Copy
fruits = fruit.copy()

Note: makes a shallow copy of a dictionary
Update
z = {1: 'One', 2: 'Two'}
x = {0: 'zero', 1: 'one'}
x.update(z)                          # results in {0: 'zero', 1: 'One', 2: 'Two'}

Note: combines the entries of two dictionaries
More dictionary Examples
fruit = {"orange": "a sweet, orange, citrus fruit",
         "apple": "good for making cider",
         "lemon": "a sour, yellow citrus fruit",
         "grape": "a small, sweet fruit growing in bunches",
         "lime": "a sour, green citrus fruit",
         "smelly fruit": "horrible smelly fruit"}

print(fruit.get('orange'))
print(fruit.get('xxxx', 'banana'))

# add to dictionary
fruit["pear"] = "an odd shape apple"

# overwrite element
fruit["lime"] = "great with tequila"

# delete a element
del fruit["smelly fruit"]

print(fruit)
print(fruit["lemon"])
print(fruit["lime"])

for key in fruit:
    print("{}: {}".format(key, fruit[key]))

for key, value in fruit.items():
    print("{}: {}".format(key, value))

print("\nOrdered list: ")
for key in sorted(list(fruit.keys())):
    print("\t{}: {}".format(key, fruit[key]))

# get tuples from dictionary, you can also go the other way
f_tuple = tuple(fruit.items())
print(f_tuple)

print("\n---------------------------------------------------------------------")

bike = {"make": "Honda", "model": "250 dream", "color": "red", "engine_size": 250}
print(bike)
print(bike["engine_size"])

print("\n---------------------------------------------------------------------")
A small game using dictionaries
locations = {0: {"desc": "You are sitting in front of a computer learning Python",
                 "exits": {},
                 "namedExits": {}},
             1: {"desc": "You are standing at the end of a road before a small brick building",
                 "exits": {"W": 2, "E": 3, "N": 5, "S": 4, "Q": 0},
                 "namedExits": {"2": 2, "3": 3, "5": 5, "4": 4}},
             2: {"desc": "You are at the top of a hill",
                 "exits": {"N": 5, "Q": 0},
                 "namedExits": {"5": 5}},
             3: {"desc": "You are inside a building, a well house for a small stream",
                 "exits": {"W": 1, "Q": 0},
                 "namedExits": {"1": 1}},
             4: {"desc": "You are in a valley beside a stream",
                 "exits": {"N": 1, "W": 2, "Q": 0},
                 "namedExits": {"1": 1, "2": 2}},
             5: {"desc": "You are in the forest",
                 "exits": {"W": 2, "S": 1, "Q": 0},
                 "namedExits": {"2": 2, "1": 1}}
             }

vocabulary = {"QUIT": "Q",
              "NORTH": "N",
              "SOUTH": "S",
              "EAST": "E",
              "WEST": "W",
              "ROAD": "1",
              "HILL": "2",
              "BUILDING": "3",
              "VALLEY": "4",
              "FOREST": "5"}

loc = 1
while True:
    availableExits = ", ".join(locations[loc]["exits"].keys())

    print(locations[loc]["desc"])

    if loc == 0:
        break
    else:
        allExits = locations[loc]["exits"].copy()
        allExits.update(locations[loc]["namedExits"])

    direction = input("Available exits are " + availableExits + ": ").upper()
    print()

    # Parse the user input, using our vocabulary dictionary if necessary
    if len(direction) > 1:  # more than 1 letter, so check vocab
        words = direction.split()
        for word in words:
            if word in vocabulary:  # does it contain a word we know?
                direction = vocabulary[word]
                break

    if direction in allExits:
        loc = allExits[direction]
    else:
        print("You cannot go in that direction")

You can use many objects as keys in dictionaries but it must be immutable and hashable

Python Type Immutable? Hashable? Dictionary Key?
int Yes Yes Yes
float Yes Yes Yes
boolean Yes Yes Yes
complex Yes Yes Yes
str Yes Yes Yes
bytes Yes Yes Yes
bytearray No No No
list No No No
tuple Yes Sometimes Sometimes
set No No No
frozenset Yes Yes Yes
dictionary No No No

Sparse Matrices

A matrix is a two-dimensional grid of numbers, it written in text book as a grid with square brackets on each side. This can easily be preresented by using a multi-array list, but for example weather forcasting it common to have very large matrices spanning tousand or millions of elements. To conserve memory iot common for such matrices to be stored in a form in which only non-zero elements are actually stored, this representations are called sparse matrices. You can implement this by using dictionaries and tuple indices. If you’re considering doing extensive work with matrices, you may want to look into NumPy, the numeric computation package.

Sparse Matrices
matrix = {(0, 0): 3, (0, 2): -2, (0, 3): 11,
(1, 1): 9, (2, 1): 7, (3, 3): -5}

# you can use the below to obtain a element
if (rownum, colnum) in matrix:
    element = matrix[(rownum, colnum)]
else:
    element = 0

# same as above but easier
element = matrix.get((rownum, colnum), 0)

Dictionaries as Caches

You can use dictionaries as a caches, if the result is already in dictionary (cache) this can be returned instead of recalculating the value.

Dictionary cache
sole_cache = {}
          
def sole(m, n, t):
    if (m, n, t) in sole_cache:
        return sole_cache[(m, n, t)]                             # return the already cached result
    else:
        # . . . do some time-consuming calculations . . .
        sole_cache[(m, n, t)] = result
        return result