Create a Hash Table / '! !' is that an operator? / logical OR {}?

let HashTable = function() {
  this.collection = {};
  // Only change code below this line
  this.add = (key, value) => {
    const hashedKey = hash(key);
    this.collection[hashedKey] = this.collection[hashedKey] || {}; *
    this.collection[hashedKey][key] = value;
  }

  this.lookup = (key) => {
    const hashedKey = hash(key);
    return this.collection[hashedKey][key];
  }

  this.remove = (key) => {
    const hashedKey = hash(key);
    delete this.collection[hashedKey][key];
    if (!!Object.keys(this.collection[hashedKey]).length) *
      delete this.collection[hashedKey];
  }
  // Only change code above this line
};

Can someone help me understand the lines of code that have a ‘*’ next to them?

Also, do we access Maps with two brackets as well?

This isn’t my favorite challenge.

A Javascript object is a hash map with unique keys, so this challenge is asking you to ignore the built in collision management and make your own.

It would be easiest to explain these if I could compare the solution to yours. What do you have?

1 Like

Thank you. My questions (in the title) are about the syntax. I don’t have code to show. Can you help me understand?

I’d recommend solving the challenge before looking up the answer… Getting the check marks isn’t really the point - practice is.

! is the logical negation operator, with coercion of non-boolean values. Thus…!! negates the negation, or is a shorthand boolean coercion.

‘logical OR {}’ isn’t really a full question. That line uses short circuiting to return the first truthy value of the two arguments to the logical OR.

1 Like

I tried before checking. Thank you so much for understanding my questions. I have some more because I need to know specifics, please.

  • Is the line, ‘this.collection[hashedKey][key]’, handling collision? If so how?

  • If the value ‘{}’ won the ‘||’ evaluation then (I’m assuming) the next line would simply store the value, right?

  • How is two ‘!’ operators any different from using none? Wouldn’t a return value of zero evaluate to falsy?

Thank you!

Here’s what I had done before posting. I didn’t want to share earlier as to not confuse the topic (interesting syntax, not the solution per se):

var HashTable = function() {

  this.collection = {};

  // Only change code below this line

  this.add = function(str, value){

    const key = hash(str);

    let index = this.collection[key];

    if(this.lookup(str)){

      index = {...index, value}

    } else{

      this.collection[key] = value;        

    }

  }

  this.remove = function(str){

    const key = hash(str);

    delete this.collection[key];

  }

  this.lookup = function(str){

    const key = hash(str);

    return this.collection[key];

  }

  // Only change code above this line

};

Again… It would be much, much more fruitful to debug your code than try to understand somebody else’s solution. I’d be happy to help you get your code working. Writing code and reading code are two different skills, and practicing reading doesn’t help you write code.

Your first question doesn’t really make sense. Collision means that two keys have the same hash. If you reset the value associated with a key, that is not a collision.

I’m not sure what ‘simply store the value’ means to you. That line creates this.collection[hashedKey] an an empty object if it doesn’t exist.

!! coerces to a boolean value. It will have the same effect in an if statement, but the author of this code wanted to explicitly coerce to a boolean value instead of implicitly.

1 Like

Cool. Thanks man. I really appreciate that you’ve been answering. I fixed my questions. Sorry about that!

Here’s when your solution starts going awry.

Big picture here:

In a hash table you take a key of any length and create a hash of a reduced length. It’s easier to index into the lookup table with the smaller hash value.

Real hashes rarely collide (map two different keys to the same hash), but you still have to consider what to do if you have a collision.

So, the hard part of this challenge is figuring out a way to store multiple keys with the same hash and return the right associated value.

So you have a few issues going on with making that work.

This gets whatever is stored at collection[key]… But here

Here you are trying to update the value instead of the collection.

Also, you still have broken the connection between the original key and the value.

So… The key to this challenge is storing both the key and the value in a sensible way associated with collection[hash]

1 Like

I guess what’s flying above my head are the tools to store multiple values at the same index. Looking at this as an array w/ a hash function & modulus arithmetic to map to indices, I don’t understand how one index (even in the solution in question, originally), can store multiple values. There’s the concept of using linked list at every index but that’s not how the solution accomplishes this. What is the interpreter doing when … :
add( …
this.collection[hashedKey][key] = value; // when it reads this line and collision is afoot?

What are some of the first data structures that you learned that can hold multiple values?

There isn’t anything fancy like a linked list here.

1 Like

In the same index/location? none. But I’m starting to assume that’s also what’s not happening here.

Nothing saves multiple values to the same place, that’s correct. You can’t put two things in the same memory location.

But there do exist complex data structures that are all about containing multiple values like arrays and objects

1 Like

I’ve taken the time to study hash tables in greater detail. I’ve come to the real dilemma I face with digesting the info. If we take a key to generate an index yet store both they key and value, how many times can we use the ‘’ operator? Is the answer thrice?

Is the following example, extending from the same FCC hashtable challenge, runnable code:
this.collection[index][key][value]

I passed the most tests w/ this code:

var called = 0;
var hash = string => {
  called++;
  var hashed = 0;
  for (var i = 0; i < string.length; i++) {
    hashed += string.charCodeAt(i);
  }
  return hashed;
};
var HashTable = function() {
  this.collection = {};
  // Only change code below this line
  this.add = function(keyValue, value){
    const indexKey = hash(keyValue);
    this.collection[indexKey] = value;
  }
  
  this.remove = function(keyValue){
    const indexKey = hash(keyValue);
    delete this.collection[indexKey];
  }
  
  this.lookup = function(keyValue){
    const indexKey = hash(keyValue);
    return this.collection[indexKey] ;
  }
  // Only change code above this line
}

The only tests I can’t pass are:
TEST: The remove method should only remove the correct key value pair.
TEST: The hash table should handle collisions.

This is where I’m trying to get at with storing the original key. You still aren’t storing the original key, so you can’t distinguish collisions.

Challenge link: https://www.freecodecamp.org/learn/coding-interview-prep/data-structures/create-a-hash-table

Try this code. What do you see?

var called = 0;
var hash = string => {
  called++;
  var hashed = 0;
  for (var i = 0; i < string.length; i++) {
    hashed += string.charCodeAt(i);
  }
  return hashed;
};
var HashTable = function () {
  this.collection = {};
  // Only change code below this line
  this.add = function (keyValue, value) {
    const indexKey = hash(keyValue);
    console.log("the hash for", keyValue, "is", indexKey);
    this.collection[indexKey] = value;
  }

  this.remove = function (keyValue) {
    const indexKey = hash(keyValue);
    console.log("removing all data associated with hash", indexKey);
    delete this.collection[indexKey];
  }

  this.lookup = function (keyValue) {
    const indexKey = hash(keyValue);
    return this.collection[indexKey];
  }
  // Only change code above this line
};

let hashTable = new HashTable;

console.log("adding value for key 'pats'");
hashTable.add("pats", 2);
console.log("value added: ", hashTable.lookup("pats"));

console.log("\nadding value for the key 'spat'");
hashTable.add("spat", 42);
console.log("value: ", hashTable.lookup("spat"));

console.log("\nchecking value for the key 'pats'");
console.log("value: ", hashTable.lookup("pats"));
1 Like

I see a mess but I finally get the solution. We need to first instantiate an object, in place /at index (i.e. ‘{}’ notation) per addition, to hold each key-value pair added. Nice.

Good work. Like I said, the challenge is a bit funko and not my favorite… It misses the essence of hash tables.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.