2
\$\begingroup\$

I have implemented a hash table. It works well. But if you think something needs to be improved, say it. This code was tested in Python 3.7.4.

class Hashtable:
    def __init__(self,size):
        self.size = size
        self.mainList = [[] for i in range(0,1)for j in range(self.size)] 
    def index(self,key):
        #To get the index number.
        asciiValue = 0
        for i in key:
            asciiValue = asciiValue + ord(i)
        index = asciiValue % self.size
        return index
    def put(self,key,value):
        #To add value to the list.
        index = self.index(key)
        self.mainList[index].append((key,value))
    def get(self,key):
        #To get value from the list
        index = self.index(key)
        for i in range(0,len(self.mainList[index])):
            if self.mainList[index][i][0] == key:
                return self.mainList[index][i][1]
        return "This key cannot be found."
\$\endgroup\$
  • \$\begingroup\$ It will help your question if you tell us a little bit more about why you wrote this code (for fun, to learn something, for a specific task, ...) and how you intend to use your class, i.e. a little usage example. \$\endgroup\$ – AlexV Oct 9 '19 at 6:44
  • \$\begingroup\$ I'm learning the data structures inside Python. I just wrote this code to learn. \$\endgroup\$ – Brijesh Kalkani Oct 9 '19 at 6:52
3
\$\begingroup\$

"magic" method

If you're learning the data structures in Python, I would read about the python data model and Collections abstract base classes to see what magic methods you can/should implement. A Hashmap is a mapping, so it should implement __getitem__, __iter__, __len__, __contains__, keys, items, values, get, __eq__, and __ne__

return vs exception

In case your mapping does not find a key, it returns "This key cannot be found.". This means users of your code should check against this sentinel value when retrieving something. What if that is the value they want to store in this mapping? The correct way to handle a missing key, is to raise an Exception. More specifically a KeyError

range

for i in range(0,1) is equivalent to range(1), so it only yields 0, which means that in this list comprehension it does nothing.

[[] for j in range(self.size)] 

Would hav achieved the same. [[]] * self.size would not have worked, since the reference to the same inner list would have been copied.

variable names

size is not the size of the mapping, but the size of the hash table, so this name might be confusing. Moreover, this should not be a public variable of the, so _hashtable_size would be more appropriate.

According to PEP-8, variable names should be snake_case, so mainList would be _main_list

get

For a dict and a mapping, get has another argument default, which gets returned if the key is missing

iteration

In python, it is seldomly necessary to iterate over the index , like you do in for i in range(0,len(self.mainList[index])):

for dict_key, value in self.mainList[index]:
    if dict_key == key:
        return value

achieves the same, but is a lot more clearer and concise

docstrings

Python has a convention on how to document a method. It's called docstrings. Instead of a #, you use a """

def put(self, key, value):
    """To add value to the list."""

class Hashtable:
    def __init__(self, size):
        """explanation what this class does, and what the argument means"""
        self._hastable_size = size
        self._main_list = [[] for j in range(size)]

    def _index(self, key):
        # To get the index number.
        return sum(ord(i) for i in key) % self._hastable_size

    def __contains__(self, key):
        index = self._index(key)
        return any(dict_key == key for dict_key in self._main_list[index])

    def put(self, key, value):
        """To add value to the list."""
        if key in self:  # calls self.__contains__(key)
            raise ValueError(f"<{key}> already present")
            # you can also choose to overwrite the already present value
        index = self._index(key)
        self._main_list[index].append((key, value))

    __setitem__ = put

    def __getitem__(self, key):
        if key not in self:
            raise KeyError(f"<{key}> not present")
        index = self._index
        for dict_key, value in self._main_list[index]:
            if dict_key == key:
                return value

    def get(self, key, default=None):
        # To get value from the list
        try:
            return self[key]
        except KeyError:
            return default

    def __len__(self):
        return sum(len(sublist) for sublist in self._main_list)

    ...
\$\endgroup\$
  • \$\begingroup\$ Thank you for a Maarten Fabré to spent your valuable time to get the review of my code. Let me correct as per your suggestion and get back to you. Today I learned many coding fundamentals and styles from your suggestions. Thanks a lot once again. \$\endgroup\$ – Brijesh Kalkani Oct 9 '19 at 9:15
  • 1
    \$\begingroup\$ don't correct your original question. Try to take this advice, and any other you might find on this site, and if you have a new version, pose a new question \$\endgroup\$ – Maarten Fabré Oct 9 '19 at 9:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.