Skip to content

Instantly share code, notes, and snippets.

@toddlucas
Last active August 29, 2015 14:12
Show Gist options
  • Save toddlucas/00d4944a2aa56037073a to your computer and use it in GitHub Desktop.
Save toddlucas/00d4944a2aa56037073a to your computer and use it in GitHub Desktop.
JavaScript Ordered Hash

Ordered Hash

These collection classes are two simple wrappers around native JavaScript objects and arrays. The goal is to leverage the benefits of each, combining the key-based access of the object type with the ordering of the array type. Although they are written in TypeScript, the equivalent JavaScript is provided for those who don't wish to use TypeScript in their projects.

Keys

The JavaScript object type allows a property to be indexed by string or by symbol. Because these collections wrap the object, providing access through methods, the symbol accessor can't be used (unless directly accessing the underlying object). This means that strings should only be used as keys. Rather than mark the key type as string, it was left as any. The reason is that doing so would require all keys to be converted to strings prior to calling the relevant methods. Leaving the key type as any leverages the normal object behavior, which is to convert the value to a string prior to using it as the property name. This makes it possible to index by number, for example.

/**
* A hash in which the keys are available as an ordered array (keys).
*/
var OrderedHash = (function () {
function OrderedHash() {
this.keys = [];
this.vals = {};
}
/**
* Tests for the existence of a key
* @returns {Boolean} true if found.
*/
OrderedHash.prototype.exists = function (k) {
return k in this.vals;
};
/**
* Appends a key and its associated value.
* The order of appended keys is preserved.
*/
OrderedHash.prototype.push = function (k, v) {
if (!this.exists(k))
this.keys.push(k);
this.vals[k] = v;
};
/**
* Find the index of a key (linear search is O(n)).
* @returns {Number} The index of the key, if present, or -1.
*/
OrderedHash.prototype.find = function (k) {
if (this.exists(k)) {
for (var i = 0; i < this.keys.length; i++) {
if (this.keys[i] === k) {
return i;
}
}
}
return -1;
};
/**
* Inserts a key and value at the specified position.
* @returns {Boolean} true if inserted or false if the key already exists.
*/
OrderedHash.prototype.insert = function (pos, k, v) {
if (this.exists(k)) {
return false;
}
this.keys.splice(pos, 0, k);
this.vals[k] = v;
return true;
};
/**
* Removes one or more elements starting at the specified position.
*/
OrderedHash.prototype.remove = function (pos, howMany) {
if (howMany === void 0) { howMany = 1; }
var k = this.keys.splice(pos, howMany);
for (var i = 0; i < this.keys.length; i++) {
delete this.vals[k[i]];
}
};
/**
* Removes an element by key (linear search is O(n)).
* @returns {Boolean} true if removed, false otherwise.
*/
OrderedHash.prototype.delete = function (k) {
if (this.exists(k)) {
for (var i = 0; i < this.keys.length; i++) {
if (this.keys[i] === k) {
this.remove(i);
return true;
}
}
}
return false;
};
/** Returns the value by key. */
OrderedHash.prototype.value = function (k) {
return this.vals[k];
};
/** Returns the length of the collection. */
OrderedHash.prototype.length = function () {
return this.keys.length;
};
return OrderedHash;
})();
module.exports = OrderedHash;
/**
* A hash in which the keys are available as an ordered array (keys).
*/
class OrderedHash {
keys = [];
vals = {};
/**
* Tests for the existence of a key
* @returns {Boolean} true if found.
*/
exists(k: any): boolean {
return k in this.vals;
}
/**
* Appends a key and its associated value.
* The order of appended keys is preserved.
*/
push(k: any, v: any): void {
if (!this.exists(k)) this.keys.push(k);
this.vals[k] = v;
}
/**
* Find the index of a key (linear search is O(n)).
* @returns {Number} The index of the key, if present, or -1.
*/
find(k: any): number {
if (this.exists(k)) {
for (var i = 0; i < this.keys.length; i++) {
if (this.keys[i] === k) {
return i;
}
}
}
return -1;
}
/**
* Inserts a key and value at the specified position.
* @returns {Boolean} true if inserted or false if the key already exists.
*/
insert(pos: number, k: any, v: any): boolean {
if (this.exists(k)) {
return false;
}
this.keys.splice(pos, 0, k);
this.vals[k] = v;
return true;
}
/**
* Removes one or more elements starting at the specified position.
*/
remove(pos: number, howMany: number = 1): void {
var k = this.keys.splice(pos, howMany);
for (var i = 0; i < this.keys.length; i++) {
delete this.vals[k[i]];
}
}
/**
* Removes an element by key (linear search is O(n)).
* @returns {Boolean} true if removed, false otherwise.
*/
delete(k: any): boolean {
if (this.exists(k)) {
for (var i = 0; i < this.keys.length; i++) {
if (this.keys[i] === k) {
this.remove(i);
return true;
}
}
}
return false;
}
/** Returns the value by key. */
value(k): any { return this.vals[k] }
/** Returns the length of the collection. */
length(): number { return this.keys.length }
}
export = OrderedHash;
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var OrderedHash = require('./OrderedHash');
/**
* An ordered hash in which the values are also available as an ordered array (list).
*/
var OrderedHashArray = (function (_super) {
__extends(OrderedHashArray, _super);
function OrderedHashArray() {
_super.apply(this, arguments);
this.list = [];
}
/**
* Appends a key and its associated value.
* The order of appended keys is preserved.
*/
OrderedHashArray.prototype.push = function (k, v) {
if (!this.exists(k)) {
this.keys.push(k);
this.list.push(v);
}
this.vals[k] = v;
};
/**
* Inserts a key and value at the specified position.
* @returns {Boolean} true if inserted or false if the key already exists.
*/
OrderedHashArray.prototype.insert = function (pos, k, v) {
if (this.exists(k)) {
return false;
}
this.keys.splice(pos, 0, k);
this.list.splice(pos, 0, v);
this.vals[k] = v;
return true;
};
/**
* Removes one or more elements starting at the specified position.
*/
OrderedHashArray.prototype.remove = function (pos, howMany) {
if (howMany === void 0) { howMany = 1; }
this.list.splice(pos, howMany);
_super.prototype.remove.call(this, pos, howMany);
};
return OrderedHashArray;
})(OrderedHash);
module.exports = OrderedHashArray;
import OrderedHash = require('./OrderedHash');
/**
* An ordered hash in which the values are also available as an ordered array (list).
*/
class OrderedHashArray extends OrderedHash {
list = [];
/**
* Appends a key and its associated value.
* The order of appended keys is preserved.
*/
push(k: any, v: any): void {
if (!this.exists(k)) {
this.keys.push(k);
this.list.push(v);
}
this.vals[k] = v;
}
/**
* Inserts a key and value at the specified position.
* @returns {Boolean} true if inserted or false if the key already exists.
*/
insert(pos: number, k: any, v: any): boolean {
if (this.exists(k)) {
return false;
}
this.keys.splice(pos, 0, k);
this.list.splice(pos, 0, v);
this.vals[k] = v;
return true;
}
/**
* Removes one or more elements starting at the specified position.
*/
remove(pos: number, howMany: number = 1): void {
this.list.splice(pos, howMany);
super.remove(pos, howMany);
}
}
export = OrderedHashArray;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment