@@ -54,6 +54,14 @@ def _get_next_ind(self, ind: int) -> int:
54
54
Get next index.
55
55
56
56
Implements linear open addressing.
57
+ >>> HashMap(5)._get_next_ind(3)
58
+ 4
59
+ >>> HashMap(5)._get_next_ind(5)
60
+ 1
61
+ >>> HashMap(5)._get_next_ind(6)
62
+ 2
63
+ >>> HashMap(5)._get_next_ind(9)
64
+ 0
57
65
"""
58
66
return (ind + 1 ) % len (self ._buckets )
59
67
@@ -82,6 +90,14 @@ def _is_full(self) -> bool:
82
90
Return true if we have reached safe capacity.
83
91
84
92
So we need to increase the number of buckets to avoid collisions.
93
+
94
+ >>> hm = HashMap(2)
95
+ >>> hm._add_item(1, 10)
96
+ >>> hm._add_item(2, 20)
97
+ >>> hm._is_full()
98
+ True
99
+ >>> HashMap(2)._is_full()
100
+ False
85
101
"""
86
102
limit = len (self ._buckets ) * self ._capacity_factor
87
103
return len (self ) >= int (limit )
@@ -114,17 +130,104 @@ def _iterate_buckets(self, key: KEY) -> Iterator[int]:
114
130
ind = self ._get_next_ind (ind )
115
131
116
132
def _add_item (self , key : KEY , val : VAL ) -> None :
133
+ """
134
+ Try to add 3 elements when the size is 5
135
+ >>> hm = HashMap(5)
136
+ >>> hm._add_item(1, 10)
137
+ >>> hm._add_item(2, 20)
138
+ >>> hm._add_item(3, 30)
139
+ >>> hm
140
+ HashMap(1: 10, 2: 20, 3: 30)
141
+
142
+ Try to add 3 elements when the size is 5
143
+ >>> hm = HashMap(5)
144
+ >>> hm._add_item(-5, 10)
145
+ >>> hm._add_item(6, 30)
146
+ >>> hm._add_item(-7, 20)
147
+ >>> hm
148
+ HashMap(-5: 10, 6: 30, -7: 20)
149
+
150
+ Try to add 3 elements when size is 1
151
+ >>> hm = HashMap(1)
152
+ >>> hm._add_item(10, 13.2)
153
+ >>> hm._add_item(6, 5.26)
154
+ >>> hm._add_item(7, 5.155)
155
+ >>> hm
156
+ HashMap(10: 13.2)
157
+
158
+ Trying to add an element with a key that is a floating point value
159
+ >>> hm = HashMap(5)
160
+ >>> hm._add_item(1.5, 10)
161
+ >>> hm
162
+ HashMap(1.5: 10)
163
+
164
+ 5. Trying to add an item with the same key
165
+ >>> hm = HashMap(5)
166
+ >>> hm._add_item(1, 10)
167
+ >>> hm._add_item(1, 20)
168
+ >>> hm
169
+ HashMap(1: 20)
170
+ """
117
171
for ind in self ._iterate_buckets (key ):
118
172
if self ._try_set (ind , key , val ):
119
173
break
120
174
121
175
def __setitem__ (self , key : KEY , val : VAL ) -> None :
176
+ """
177
+ 1. Changing value of item whose key is present
178
+ >>> hm = HashMap(5)
179
+ >>> hm._add_item(1, 10)
180
+ >>> hm.__setitem__(1, 20)
181
+ >>> hm
182
+ HashMap(1: 20)
183
+
184
+ 2. Changing value of item whose key is not present
185
+ >>> hm = HashMap(5)
186
+ >>> hm._add_item(1, 10)
187
+ >>> hm.__setitem__(0, 20)
188
+ >>> hm
189
+ HashMap(0: 20, 1: 10)
190
+
191
+ 3. Changing the value of the same item multiple times
192
+ >>> hm = HashMap(5)
193
+ >>> hm._add_item(1, 10)
194
+ >>> hm.__setitem__(1, 20)
195
+ >>> hm.__setitem__(1, 30)
196
+ >>> hm
197
+ HashMap(1: 30)
198
+ """
122
199
if self ._is_full ():
123
200
self ._size_up ()
124
201
125
202
self ._add_item (key , val )
126
203
127
204
def __delitem__ (self , key : KEY ) -> None :
205
+ """
206
+ >>> hm = HashMap(5)
207
+ >>> hm._add_item(1, 10)
208
+ >>> hm._add_item(2, 20)
209
+ >>> hm._add_item(3, 30)
210
+ >>> hm.__delitem__(3)
211
+ >>> hm
212
+ HashMap(1: 10, 2: 20)
213
+ >>> hm = HashMap(5)
214
+ >>> hm._add_item(-5, 10)
215
+ >>> hm._add_item(6, 30)
216
+ >>> hm._add_item(-7, 20)
217
+ >>> hm.__delitem__(-5)
218
+ >>> hm
219
+ HashMap(6: 30, -7: 20)
220
+
221
+ # Trying to remove a non-existing item
222
+ >>> hm = HashMap(5)
223
+ >>> hm._add_item(1, 10)
224
+ >>> hm._add_item(2, 20)
225
+ >>> hm._add_item(3, 30)
226
+ >>> hm.__delitem__(4)
227
+ Traceback (most recent call last):
228
+ ...
229
+ KeyError: 4
230
+ """
128
231
for ind in self ._iterate_buckets (key ):
129
232
item = self ._buckets [ind ]
130
233
if item is None :
@@ -156,7 +259,13 @@ def __iter__(self) -> Iterator[KEY]:
156
259
yield from (item .key for item in self ._buckets if item )
157
260
158
261
def __repr__ (self ) -> str :
159
- val_string = " , " .join (
262
+ val_string = ", " .join (
160
263
f"{ item .key } : { item .val } " for item in self ._buckets if item
161
264
)
162
265
return f"HashMap({ val_string } )"
266
+
267
+
268
+ if __name__ == "__main__" :
269
+ import doctest
270
+
271
+ doctest .testmod ()
0 commit comments