From 400dc8b55a974afe6823e5bf325660b763c78e4e Mon Sep 17 00:00:00 2001 From: Donne Martin Date: Sun, 16 Oct 2016 21:28:31 -0400 Subject: [PATCH] Update hash map (#104) Update constraints, test cases, algorithm, code, and tests. --- .../hash_map/hash_map_challenge.ipynb | 26 +++++++----- .../hash_map/hash_map_solution.ipynb | 40 +++++++++++-------- arrays_strings/hash_map/test_hash_map.py | 8 ++-- 3 files changed, 42 insertions(+), 32 deletions(-) diff --git a/arrays_strings/hash_map/hash_map_challenge.ipynb b/arrays_strings/hash_map/hash_map_challenge.ipynb index b08e866..dd1cd55 100644 --- a/arrays_strings/hash_map/hash_map_challenge.ipynb +++ b/arrays_strings/hash_map/hash_map_challenge.ipynb @@ -39,7 +39,11 @@ "* For collision resolution, can we use chaining?\n", " * Yes\n", "* Do we have to worry about load factors?\n", - " * No" + " * No\n", + "* Do we have to validate inputs?\n", + " * No\n", + "* Can we assume this fits memory?\n", + " * Yes" ] }, { @@ -48,12 +52,12 @@ "source": [ "## Test Cases\n", "\n", - "* get on an empty hash table index\n", - "* set on an empty hash table index\n", - "* set on a non empty hash table index\n", - "* set on a key that already exists\n", - "* remove on a key with an entry\n", - "* remove on a key without an entry" + "* `get` no matching key -> KeyError exception\n", + "* `get` matching key -> value\n", + "* `set` no matchin gkey -> new key, value\n", + "* `set` matching key -> update value\n", + "* `remove` no matching key -> KeyError exception\n", + "* `remove` matching key -> remove key, value" ] }, { @@ -135,7 +139,7 @@ "outputs": [], "source": [ "# %load test_hash_map.py\n", - "from nose.tools import assert_equal\n", + "from nose.tools import assert_equal, assert_raises\n", "\n", "\n", "class TestHashMap(object):\n", @@ -146,7 +150,7 @@ " hash_table = HashTable(10)\n", "\n", " print(\"Test: get on an empty hash table index\")\n", - " assert_equal(hash_table.get(0), None)\n", + " assert_raises(KeyError, hash_table.get, 0)\n", "\n", " print(\"Test: set on an empty hash table index\")\n", " hash_table.set(0, 'foo')\n", @@ -167,10 +171,10 @@ " print(\"Test: remove on a key that already exists\")\n", " hash_table.remove(10)\n", " assert_equal(hash_table.get(0), 'foo')\n", - " assert_equal(hash_table.get(10), None)\n", + " assert_raises(KeyError, hash_table.get, 10)\n", "\n", " print(\"Test: remove on a key that doesn't exist\")\n", - " hash_table.remove(-1)\n", + " assert_raises(KeyError, hash_table.remove, -1)\n", "\n", " print('Success: test_end_to_end')\n", "\n", diff --git a/arrays_strings/hash_map/hash_map_solution.ipynb b/arrays_strings/hash_map/hash_map_solution.ipynb index c4db0a1..6282a14 100644 --- a/arrays_strings/hash_map/hash_map_solution.ipynb +++ b/arrays_strings/hash_map/hash_map_solution.ipynb @@ -35,10 +35,14 @@ "\n", "* For simplicity, are the keys integers only?\n", " * Yes\n", - "* For collision resolution, can we use linked lists?\n", + "* For collision resolution, can we use chaining?\n", " * Yes\n", "* Do we have to worry about load factors?\n", - " * No" + " * No\n", + "* Do we have to validate inputs?\n", + " * No\n", + "* Can we assume this fits memory?\n", + " * Yes" ] }, { @@ -47,12 +51,12 @@ "source": [ "## Test Cases\n", "\n", - "* get on an empty hash table index\n", - "* set on an empty hash table index\n", - "* set on a non empty hash table index\n", - "* set on a key that already exists\n", - "* remove on a key with an entry\n", - "* remove on a key without an entry" + "* `get` no matching key -> KeyError exception\n", + "* `get` matching key -> value\n", + "* `set` no matchin gkey -> new key, value\n", + "* `set` matching key -> update value\n", + "* `remove` no matching key -> KeyError exception\n", + "* `remove` matching key -> remove key, value" ] }, { @@ -83,7 +87,7 @@ "\n", "* Get hash index for lookup\n", "* If key exists, return value\n", - "* Else, return None\n", + "* Else, raise KeyError\n", "\n", "Complexity:\n", "* Time: O(1) average and best, O(n) worst\n", @@ -93,6 +97,7 @@ "\n", "* Get hash index for lookup\n", "* If key exists, delete the item\n", + "* Else, raise KeyError\n", "\n", "Complexity:\n", "* Time: O(1) average and best, O(n) worst\n", @@ -143,14 +148,15 @@ " for item in self.table[hash_index]:\n", " if item.key == key:\n", " return item.value\n", - " return None\n", + " raise KeyError('Key not found')\n", "\n", " def remove(self, key):\n", " hash_index = self.hash_function(key)\n", - " for i, item in enumerate(self.table[hash_index]):\n", + " for index, item in enumerate(self.table[hash_index]):\n", " if item.key == key:\n", - " del self.table[hash_index][i]\n", - " return" + " del self.table[hash_index][index]\n", + " return\n", + " raise KeyError('Key not found')" ] }, { @@ -177,7 +183,7 @@ ], "source": [ "%%writefile test_hash_map.py\n", - "from nose.tools import assert_equal\n", + "from nose.tools import assert_equal, assert_raises\n", "\n", "\n", "class TestHashMap(object):\n", @@ -188,7 +194,7 @@ " hash_table = HashTable(10)\n", "\n", " print(\"Test: get on an empty hash table index\")\n", - " assert_equal(hash_table.get(0), None)\n", + " assert_raises(KeyError, hash_table.get, 0)\n", "\n", " print(\"Test: set on an empty hash table index\")\n", " hash_table.set(0, 'foo')\n", @@ -209,10 +215,10 @@ " print(\"Test: remove on a key that already exists\")\n", " hash_table.remove(10)\n", " assert_equal(hash_table.get(0), 'foo')\n", - " assert_equal(hash_table.get(10), None)\n", + " assert_raises(KeyError, hash_table.get, 10)\n", "\n", " print(\"Test: remove on a key that doesn't exist\")\n", - " hash_table.remove(-1)\n", + " assert_raises(KeyError, hash_table.remove, -1)\n", "\n", " print('Success: test_end_to_end')\n", "\n", diff --git a/arrays_strings/hash_map/test_hash_map.py b/arrays_strings/hash_map/test_hash_map.py index 486f2c4..1054d70 100644 --- a/arrays_strings/hash_map/test_hash_map.py +++ b/arrays_strings/hash_map/test_hash_map.py @@ -1,4 +1,4 @@ -from nose.tools import assert_equal +from nose.tools import assert_equal, assert_raises class TestHashMap(object): @@ -9,7 +9,7 @@ class TestHashMap(object): hash_table = HashTable(10) print("Test: get on an empty hash table index") - assert_equal(hash_table.get(0), None) + assert_raises(KeyError, hash_table.get, 0) print("Test: set on an empty hash table index") hash_table.set(0, 'foo') @@ -30,10 +30,10 @@ class TestHashMap(object): print("Test: remove on a key that already exists") hash_table.remove(10) assert_equal(hash_table.get(0), 'foo') - assert_equal(hash_table.get(10), None) + assert_raises(KeyError, hash_table.get, 10) print("Test: remove on a key that doesn't exist") - hash_table.remove(-1) + assert_raises(KeyError, hash_table.remove, -1) print('Success: test_end_to_end')