Skip to content

Instantly share code, notes, and snippets.

@softwarespot
Last active April 23, 2017 13:25
Show Gist options
  • Save softwarespot/52bc400a35f4dcc0da1754d1e0b09e8e to your computer and use it in GitHub Desktop.
Save softwarespot/52bc400a35f4dcc0da1754d1e0b09e8e to your computer and use it in GitHub Desktop.
Queue & Stack implementation
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