Last active
March 25, 2016 06:21
-
-
Save jamesarosen/3bf0fd3559b5a7ddefef to your computer and use it in GitHub Desktop.
Implementing a HashTable based on JS arrays... just for fun
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default class HashTable { | |
constructor(size) { | |
this._data = new Array(size); | |
} | |
// Inserts `value` under `key`, forgetting any previous value stored under `key`. | |
// Returns the HashTable. | |
insert(key, value) { | |
bucketFor(this._data, key, true).insert(key, value); | |
return this; | |
} | |
// Returns the value stored under `key`, or `undefined` if nothing is stored there. | |
get(key) { | |
const bucket = bucketFor(this._data, key, false); | |
return bucket === undefined ? undefined : bucket.get(key); | |
} | |
// Returns `true` iff there is a value (other than `undefined`) stored under `key`. | |
has(key) { | |
return this.get(key) !== undefined; | |
} | |
// Deletes the value stored under `key`. Idempotent. | |
// Returns the HashTable. | |
remove(key) { | |
const bucket = bucketFor(this._data, key, false); | |
if (bucket) { bucket.remove(key); } | |
return this; | |
} | |
}; | |
function bucketFor(data, key, createIfEmpty) { | |
const index = indexFor(data, key); | |
let bucket = data[index]; | |
if (bucket === undefined && createIfEmpty) { | |
bucket = data[index] = new Bucket(); | |
} | |
return bucket; | |
} | |
class Bucket { | |
constructor() { | |
this._entries = []; | |
} | |
insert(key, value) { | |
const existing = this._entries.find(matchingKey(key)); | |
if (existing) { | |
existing[1] = value; | |
} else { | |
this._entries.push([ key, value ]); | |
} | |
} | |
get(key) { | |
const existing = this._entries.find(matchingKey(key)); | |
return existing === undefined ? undefined : existing[1]; | |
} | |
remove(key) { | |
const existingIndex = this._entries.findIndex(matchingKey(key)); | |
if (existingIndex) { | |
this._entries.splice(existingIndex, 1); | |
} | |
} | |
} | |
function matchingKey(target) { | |
return function([ key, _ ]) { return key === target; }; | |
} | |
const SOME_PRIME = 7; | |
const ANOTHER_PRIME = 31; | |
function indexFor(data, key) { | |
key = '' + key; | |
let hash = SOME_PRIME; | |
for (let i = 0; i < key.length; ++i) { | |
hash = hash * ANOTHER_PRIME + key.charCodeAt(i); | |
} | |
return hash % data.length; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment