Last active
April 23, 2017 13:25
-
-
Save softwarespot/52bc400a35f4dcc0da1754d1e0b09e8e to your computer and use it in GitHub Desktop.
Queue & Stack implementation
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
function Queue(iterable) { | |
if (!(this instanceof Queue)) { | |
throw new TypeError('"Queue" cannot be called as a function. Use the "new" keyword to construct a new "Queue" object'); | |
} | |
this._queue = []; | |
if (!_isArrayLike(iterable)) { | |
return; | |
} | |
_arrayForEach(_arrayFrom(iterable), function (value) { | |
this.queue(value); | |
}, this); | |
} | |
Queue.prototype = { | |
clear: function () { | |
this._queue.length = 0; | |
}, | |
delete: function (value) { | |
var index = _indexOf(this._queue, value) | |
if (index >= 0) { | |
this._queue.splice(index, 1); | |
return true; | |
} | |
return false; | |
}, | |
enqueue: function () { | |
return this._queue.shift(); | |
}, | |
entries: function () { | |
return _arrayMap(this._queue, function (value) { | |
return [value, value]; | |
}, this); | |
}, | |
forEach: function (fn, thisArg) { | |
return _arrayForEach(this._queue, function (value) { | |
fn.call(thisArg, value, value, this); | |
}, this); | |
}, | |
has: function (value) { | |
return _indexOf(this._queue, value) >= 0; | |
}, | |
queue: function (value) { | |
this._queue.push(value); | |
return this; | |
}, | |
values: function () { | |
// Create a copy of the internal array | |
return _arrayFrom(this._queue); | |
} | |
}; | |
// Define a read-only "size" property | |
Object.defineProperty(Queue.prototype, 'size', { | |
get: function () { | |
return this._queue.length; | |
} | |
}); | |
// Queue Example(s) | |
var queue = new Queue([ | |
'A', | |
'B', | |
'C' | |
]); | |
queue.queue('D'); | |
queue.queue('E'); | |
queue.queue(NaN); | |
queue.queue(NaN); | |
console.log('has::', queue.has(NaN)); | |
console.log('values::', queue.values()); | |
console.log('entries::', queue.entries()); | |
console.log('size::', queue.size); | |
queue.forEach(function (value, key, set) { | |
console.log('forEach::', value, key, set); | |
}); | |
console.log('enqueue::', queue.enqueue()); | |
console.log('values::', queue.values()); | |
queue.clear(); | |
console.log('size::', queue.size); | |
function Stack(iterable) { | |
if (!(this instanceof Stack)) { | |
throw new TypeError('"Stack" cannot be called as a function. Use the "new" keyword to construct a new "Stack" object'); | |
} | |
this._stack = []; | |
if (!_isArrayLike(iterable)) { | |
return; | |
} | |
_arrayForEach(_arrayFrom(iterable), function (value) { | |
this.push(value); | |
}, this); | |
} | |
Stack.prototype = { | |
clear: function () { | |
this._stack.length = 0; | |
}, | |
delete: function (value) { | |
var index = _indexOf(this._stack, value) | |
if (index >= 0) { | |
this._stack.splice(index, 1); | |
return true; | |
} | |
return false; | |
}, | |
entries: function () { | |
return _arrayMap(this._stack, function (value) { | |
return [value, value]; | |
}, this); | |
}, | |
forEach: function (fn, thisArg) { | |
return _arrayForEach(this._stack, function (value) { | |
fn.call(thisArg, value, value, this); | |
}, this); | |
}, | |
has: function (value) { | |
return _indexOf(this._stack, value) >= 0; | |
}, | |
pop: function () { | |
return this._stack.pop(); | |
}, | |
push: function (value) { | |
this._stack.push(value); | |
return this; | |
}, | |
values: function () { | |
// Create a copy of the internal array | |
return _arrayFrom(this._stack); | |
} | |
}; | |
// Define a read-only "size" property | |
Object.defineProperty(Stack.prototype, 'size', { | |
get: function () { | |
return this._stack.length; | |
} | |
}); | |
// Stack Example(s) | |
var stack = new Stack([ | |
'A', | |
'B', | |
'C' | |
]); | |
stack.push('D'); | |
stack.push('E'); | |
stack.push(NaN); | |
stack.push(NaN); | |
console.log('has::', stack.has(NaN)); | |
console.log('values::', stack.values()); | |
console.log('entries::', stack.entries()); | |
console.log('size::', stack.size); | |
stack.forEach(function (value, key, set) { | |
console.log('forEach::', value, key, set); | |
}); | |
console.log('pop::', stack.pop()); | |
console.log('values::', stack.values()); | |
stack.clear(); | |
console.log('size::', stack.size); | |
// Helper functions | |
// Wrapper for Array.from() | |
function _arrayFrom(array) { | |
return _arrayMap(array, function (value) { | |
return value; | |
}); | |
} | |
// Wrapper for Array.prototype.forEach() | |
function _arrayForEach(array, fn, context) { | |
return array.forEach(fn.bind(context)); | |
} | |
// Wrapper for Array.prototype.map() | |
function _arrayMap(array, fn, context) { | |
return array.map(fn.bind(context)); | |
} | |
// Array.prototype.indexOf() polyfill which supports NaN aka just like Array.prototype.includes() does | |
function _indexOf(array, search) { | |
var includeNaN = search !== search; | |
for (var i = 0; i < array.length; i++) { | |
// Similar to Object.is() and its comparison checks, since -0 !== 0 | |
if (search === array[i] ? | |
search !== 0 || (1 / search) === (1 / array[i]) : | |
includeNaN && array[i] !== array[i]) { | |
return i; | |
} | |
} | |
return -1; | |
} | |
// Check if an array-like object is array-like | |
function _isArrayLike(arrayLike) { | |
return arrayLike && | |
typeof arrayLike.length === 'number' && | |
arrayLike.length >= 0 && | |
arrayLike.length <= (Math.pow(2, 53) - 1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment