Wondering why this hashmap doesn't assign every flower

https://www.codecademy.com/paths/computer-science/tracks/complex-data-structures/modules/cspath-hash-maps/projects/blossom

Below is my code, it works pretty well except for one thing: It doesn’t assign all the “flower_definitions” into self.array. When I call for the value of keys :rose, hyacinth, and wisteria, I get returned None. I was wondering if anyone knows why?

from linked_list import Node, LinkedList
from blossom_lib import flower_definitions

class HashMap:
def init(self,size):
self.array_size=size
self.array=[LinkedList() for i in range(size)]

def hash(self,key):
hash_code=sum(key.encode())
return hash_code

def compress(self,hash_code):
dab=hash_code%self.array_size
return dab

def assign(self,key,value):
hash_code=self.hash(key)
array_index=self.compress(hash_code)
payload=Node([key,value])
list_at_array=self.array[array_index]

for i in list_at_array:
  if i[0]==key:
    i[1]=value
list_at_array.insert(payload)

def retrieve(self,key):
hash_code=self.hash(key)
array_index=self.compress(hash_code)

list_at_index=self.array[array_index]
for i in list_at_index:
  if i[0]==key:
    return i[1]
  else:
    return None

blossom=HashMap(len(flower_definitions))
for flower in flower_definitions:
blossom.assign(flower[0],flower[1])
print(blossom.retrieve(“hyacinth”))
print(flower_definitions)

Hi @focussion ,

Please format the entirety of your code so that other users can see its indentation, which is essential for defining the structure of a Python program. You can find advice on how to do that in How to ask good questions (and get good answers).

EDIT: October 3, 2018:

From a portion of your code that is formatted, it is evident that the else block within your retrieve method is matched to an if block header, due to its degree of indentation. It should, instead, be matched to the for loop header so that this line executes only if the loop completes all its iterations without finding a valid key …

    return None

I attempted this as well. By unindenting the else: return None in the .retrieve() method to be outside the if statement but in response to the for loop, it fixed my problem. I have a slight bit of confusion as to why (perhaps it’s because those 4 flowers were indexed at already filled buckets in the array, so they were the ones where linked lists were implemented), but I hope my input helps you figure out your own question!

I got the same problem here, so I’m not sure if it’s my retrieve or assign methods that are screwing up:

  def assign(self, key, value):
    array_index = self.compress(self.hash(key))
    payload = Node([key, value])
    list_at_array = self.array[array_index]
    for item in list_at_array:
      if key == item[0]:
        item[1] = value
        self.array[array_index] = list_at_array.insert(payload)
        
  def retrieve(self, key):
    array_index = self.compress(self.hash(key))
    list_at_index = self.array[array_index]
    for i in list_at_index:
      if i[0] == key:
        return i[1]
      if i[0] is None or i[0] != key:
        return
blossom = HashMap(len(flower_definitions))
for flower in flower_definitions:
  blossom.assign(flower[0], flower[1])
print(blossom.retrieve('daisy'))

@zchrybwmn,

The else header should be matched with the for header. If key is found within list_at_index, which is the bucket to which key hashes, the value associated with key gets returned and execution of the retrieve function ceases. However, if all iterations of the loop complete without key being found, then key is not in the database at all. If, and only if, a loop completes all its iterations without being interrupted, and if there is an associated else block, that block will execute. In this case, None will be the return value, indicating to us that key was not found.

2 Likes

Hi @jhern603,

Instead of this …

      if i[0] is None or i[0] != key:
        return

… create an else header that aligns with the for loop header. Inside the else block, just return None.

That block should execute if key is not found.

Regardless of the else block being formatted as that, I still get None after running script.py

@jhern603 ,

The assign method also needs some revision.

This should not be an assignment statement …

        self.array[array_index] = list_at_array.insert(payload)

It should simply be an appropriate call to the insert method, as follows …

        list_at_array.insert(payload)

Also, you should only call the insert method if the key was not found in the existing data.

Accordingly, you can rearrange the assign method as follows …

  def assign(self, key, value):
    array_index = self.compress(self.hash(key))
    payload = Node([key, value])
    list_at_array = self.array[array_index]
    for item in list_at_array:
      if key == item[0]:
        item[1] = value
        break
    else:
      list_at_array.insert(payload)

Then the else block will only execute if break was not executed because key did not already exist in the database.

1 Like