ht
Version:
Hash Table Implementation for javascript
264 lines (217 loc) • 8.9 kB
JavaScript
(function () {
"use strict";
function defineHt(_) {
var hashFunction = function (key) {
if (typeof key === "string") {
return key;
} else if (typeof key === "object") {
return key.hashCode ? key.hashCode() : "" + key;
} else {
return "" + key;
}
};
var Bucket = _.declare({
instance: {
constructor: function () {
this.__entries = [];
this.__keys = [];
this.__values = [];
},
pushValue: function (key, value) {
this.__keys.push(key);
this.__values.push(value);
this.__entries.push({key: key, value: value});
return value;
},
remove: function (key) {
var ret = null, map = this.__entries, val, keys = this.__keys, vals = this.__values;
var i = map.length - 1;
for (; i >= 0; i--) {
if (!!(val = map[i]) && val.key === key) {
map.splice(i, 1);
keys.splice(i, 1);
vals.splice(i, 1);
return val.value;
}
}
return ret;
},
"set": function (key, value) {
var ret = null, map = this.__entries, vals = this.__values;
var i = map.length - 1;
for (; i >= 0; i--) {
var val = map[i];
if (val && key === val.key) {
vals[i] = value;
val.value = value;
ret = value;
break;
}
}
if (!ret) {
map.push({key: key, value: value});
}
return ret;
},
find: function (key) {
var ret = null, map = this.__entries, val;
var i = map.length - 1;
for (; i >= 0; i--) {
val = map[i];
if (val && key === val.key) {
ret = val.value;
break;
}
}
return ret;
},
getEntrySet: function () {
return this.__entries;
},
getKeys: function () {
return this.__keys;
},
getValues: function (arr) {
return this.__values;
}
}
});
return _.declare({
instance: {
constructor: function () {
this.__map = {};
},
entrySet: function () {
var ret = [], map = this.__map;
for (var i in map) {
if (map.hasOwnProperty(i)) {
ret = ret.concat(map[i].getEntrySet());
}
}
return ret;
},
put: function (key, value) {
var hash = hashFunction(key);
var bucket = null;
if (!(bucket = this.__map[hash])) {
bucket = (this.__map[hash] = new Bucket());
}
bucket.pushValue(key, value);
return value;
},
remove: function (key) {
var hash = hashFunction(key), ret = null;
var bucket = this.__map[hash];
if (bucket) {
ret = bucket.remove(key);
}
return ret;
},
"get": function (key) {
var hash = hashFunction(key), ret = null, bucket;
if (!!(bucket = this.__map[hash])) {
ret = bucket.find(key);
}
return ret;
},
"set": function (key, value) {
var hash = hashFunction(key), ret = null, bucket = null, map = this.__map;
if (!!(bucket = map[hash])) {
ret = bucket.set(key, value);
} else {
ret = (map[hash] = new Bucket()).pushValue(key, value);
}
return ret;
},
contains: function (key) {
var hash = hashFunction(key), ret = false, bucket = null;
if (!!(bucket = this.__map[hash])) {
ret = !!(bucket.find(key));
}
return ret;
},
concat: function (hashTable) {
if (hashTable instanceof this._static) {
var ret = new this._static();
var otherEntrySet = hashTable.entrySet().concat(this.entrySet());
for (var i = otherEntrySet.length - 1; i >= 0; i--) {
var e = otherEntrySet[i];
ret.put(e.key, e.value);
}
return ret;
} else {
throw new TypeError("When joining hashtables the joining arg must be a HashTable");
}
},
filter: function (cb, scope) {
var es = this.entrySet(), ret = new this._static();
es = _.filter(es, cb, scope);
for (var i = es.length - 1; i >= 0; i--) {
var e = es[i];
ret.put(e.key, e.value);
}
return ret;
},
forEach: function (cb, scope) {
var es = this.entrySet();
_.forEach(es, cb, scope);
},
every: function (cb, scope) {
var es = this.entrySet();
return _.every(es, cb, scope);
},
map: function (cb, scope) {
var es = this.entrySet();
return _.map(es, cb, scope);
},
some: function (cb, scope) {
var es = this.entrySet();
return _.some(es, cb, scope);
},
reduce: function (cb, scope) {
var es = this.entrySet();
return _.reduce(es, cb, scope);
},
reduceRight: function (cb, scope) {
var es = this.entrySet();
return _.reduceRight(es, cb, scope);
},
clear: function () {
this.__map = {};
},
keys: function () {
var ret = [], map = this.__map;
for (var i in map) {
//if (map.hasOwnProperty(i)) {
ret = ret.concat(map[i].getKeys());
//}
}
return ret;
},
values: function () {
var ret = [], map = this.__map;
for (var i in map) {
//if (map.hasOwnProperty(i)) {
ret = ret.concat(map[i].getValues());
//}
}
return ret;
},
isEmpty: function () {
return this.keys().length === 0;
}
}
});
}
if ("undefined" !== typeof exports) {
if ("undefined" !== typeof module && module.exports) {
module.exports = defineHt(require("extended")().register("declare", require("declare.js")).register(require("is-extended")).register(require("array-extended")));
}
} else if ("function" === typeof define) {
define(["extended", "declare", "is-extended", "array-extended"], function (extended, declare, is, array) {
return defineHt(extended().register("declare", declare).register(is).register(array));
});
} else {
this.Ht = defineHt(this.extended().register("declare", this.declare).register(this.isExtended).register(this.arrayExtended));
}
}).call(this);