Exercises for Lesson 18

Back to Lesson 18

Exercise 1: Map

Your goal is to write a class named Map, which allows us to associate keys with values. For example, we may want to map the string "blue" to the number 3 and the string "yellow" to the number 4.

The Map class should have the following methods:

  • Map() constructor: takes no actual parameters, but initializes necessary data structures; returns None
  • add(key, value): adds a new mapping from key to value (or updates the mapping if key is already present); returns None
  • get(key): looks up the value mapped to by key; returns the value for key or None if no mapping exists for key
  • getSize(): calculates the number of key-value pairs; returns that number (an int)

Think carefully about what you need to store to be able to handle any number of key-value pairs.

You should create a new file named map.py and put your class definition there. It should start like this:

class Map:
    # TODO: write the class!
    pass # delete this line

To get you started, here is some code you can use to test your implementation. Copy this and save it as mapTest.py in the same folder as map.py.

## Unit tests for Map class

import unittest

from map import *

#########################################################
## constructor (by itself)                             ##
#########################################################

# For now, just make sure the class exists
class Test_1_constructor(unittest.TestCase):

    def testExists(self):
        map = Map()
        self.assertIsNotNone(map)

#########################################################
## add method (by itself)                              ##
#########################################################

# For now, just make sure add exists
class Test_2_add(unittest.TestCase):

    def testAddFromEmpty(self):
        map = Map()

        actual = map.add("blue", 314)
        self.assertIsNone(actual)

    def testAddUpdate(self):
        map = Map()

        actual = map.add("blue", 314)
        self.assertIsNone(actual)

        actual = map.add("blue", 271)
        self.assertIsNone(actual)

#########################################################
## get method (with constructor, add)                  ##
#########################################################

class Test_3_get(unittest.TestCase):

    def testGetEmpty(self):
        map = Map()

        actual = map.get("blue")
        self.assertIsNone(actual)

    def testGetNotFound(self):
        map = Map()
        map.add("blue", 314)
        
        actual = map.get("yellow")
        self.assertIsNone(actual)

    def testGetSinglePair(self):
        map = Map()
        key = "blue"
        value = 314
        map.add(key, value)

        expected = value
        actual = map.get(key)
        self.assertEqual(expected, actual)

    def testGetMultiplePairs(self):
        map = Map()
        key = "blue"
        value = 314
        map.add(key, value)
        map.add("yellow", 271)

        expected = value
        actual = map.get(key)
        self.assertEqual(expected, actual)

    def testGetUpdated(self):
        map = Map()
        key = "blue"
        oldValue = 314
        newValue = 271
        map.add(key, oldValue)
        map.add(key, newValue)

        expected = newValue
        actual = map.get(key)
        self.assertEqual(expected, actual)

#########################################################
## get method (with constructor, add)                  ##
#########################################################

class Test_4_getSize(unittest.TestCase):

    def testGetSizeEmpty(self):
        map = Map()
        
        expected = 0
        actual = map.getSize()
        self.assertEqual(expected, actual)

    def testGetSizeSinglePair(self):
        map = Map()
        map.add("blue", 314)

        expected = 1
        actual = map.getSize()
        self.assertEqual(expected, actual)

    def testGetSizeMultiplePairs(self):
        map = Map()
        map.add("blue", 314)
        map.add("yellow", 271)

        expected = 2
        actual = map.getSize()
        self.assertEqual(expected, actual)

    def testGetSizeUpdated(self):
        map = Map()
        map.add("blue", 314)
        map.add("blue", 271)

        expected = 1
        actual = map.getSize()
        self.assertEqual(expected, actual)

#########################################################
## run tests                                           ##
#########################################################

if __name__ == "__main__":
    unittest.main(verbosity=2)

At first, all tests should fail. When I run it (python3 mapTest.py in Mac/Linux or python.exe mapTest.py in Windows), it gives a bunch of output, ending like this:

...
======================================================================
ERROR: testGetSizeUpdated (__main__.Test_4_getSize.testGetSizeUpdated)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\me\cs111\lesson18\mapTest.py", line 124, in testGetSizeUpdated
    map.add("blue", 314)
    ^^^^^^^
AttributeError: 'Map' object has no attribute 'add'

----------------------------------------------------------------------
Ran 12 tests in 0.004s

FAILED (errors=11)

Once you have the class fully implemented, running the tests should give the following output:

testExists (__main__.Test_1_constructor.testExists) ... ok
testAddFromEmpty (__main__.Test_2_add.testAddFromEmpty) ... ok
testAddUpdate (__main__.Test_2_add.testAddUpdate) ... ok
testGetEmpty (__main__.Test_3_get.testGetEmpty) ... ok
testGetMultiplePairs (__main__.Test_3_get.testGetMultiplePairs) ... ok
testGetNotFound (__main__.Test_3_get.testGetNotFound) ... ok
testGetSinglePair (__main__.Test_3_get.testGetSinglePair) ... ok
testGetUpdated (__main__.Test_3_get.testGetUpdated) ... ok
testGetSizeEmpty (__main__.Test_4_getSize.testGetSizeEmpty) ... ok
testGetSizeMultiplePairs (__main__.Test_4_getSize.testGetSizeMultiplePairs) ... ok
testGetSizeSinglePair (__main__.Test_4_getSize.testGetSizeSinglePair) ... ok
testGetSizeUpdated (__main__.Test_4_getSize.testGetSizeUpdated) ... ok

----------------------------------------------------------------------
Ran 12 tests in 0.005s

OK

Back to Lesson 18