Last active
December 20, 2015 21:09
-
-
Save Maksims/6195423 to your computer and use it in GitHub Desktop.
Collections that promise for single appearance of object in collection as well as use hashing based on key (if defined) for collection to speed up checks. In small collections that slows down (nearly unmeasurable) but in 'big' collections (32+) it is a great win to prevent iterations for searches.
This file contains 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
'use strict'; | |
var Collection = this.Collection = exports.Collection = function Collection(key) { | |
this.list = [ ]; | |
this.length = 0; | |
this.key = key || null; | |
this.map = { }; | |
} | |
// get if collection has item by function or item | |
Collection.prototype.has = function has(fnOrItem) { | |
if (typeof(fnOrItem) === 'function') { // function | |
for(var i = 0, len = this.list.length; i < len; ++i) { | |
if (fnOrItem(this.list[i])) { | |
return true; | |
} | |
} | |
} else { // item | |
if (this.key) { | |
return this.map[fnOrItem[this.key]] !== undefined; | |
} else { | |
for(var i = 0, len = this.list.length; i < len; ++i) { | |
if (this.list[i] === fnOrItem) { | |
return true; | |
} | |
} | |
} | |
} | |
return false; | |
}; | |
// add item if not in list | |
Collection.prototype.push = function push(item) { | |
if (item instanceof Array) { // array | |
if (this.key) { | |
for(var i = 0, len = item.length; i < len; i++) { | |
if (this.map[item[i][this.key]] === undefined) { | |
this.list.push(item[i]); | |
this.map[item[i][this.key]] = item[i]; | |
} | |
} | |
} else { | |
for(var n = 0, lenP = item.length; n < lenP; n++) { | |
for(var i = 0, len = this.list.length; i < len; i++) { | |
if (this.list[i] !== item) { | |
this.list.push(item[n]); | |
} | |
} | |
} | |
} | |
} else { // single | |
if (this.key) { | |
if (this.map[item[this.key]] !== undefined) { | |
return; | |
} | |
this.list.push(item); | |
this.map[item[this.key]] = item; | |
} else { | |
for(var i = 0, len = this.list.length; i < len; i++) { | |
if (this.list[i] === item) { | |
return; | |
} | |
} | |
this.list.push(item); | |
} | |
} | |
this.length = this.list.length; | |
}; | |
// removes item from collection and returns it based on filter function or item | |
Collection.prototype.pull = function pull(fnOrKey) { | |
if (typeof(fnOrKey) === 'function') { // function | |
for(var i = 0, len = this.list.length; i < len; i++) { | |
item = this.list[i]; | |
if (fnOrKey(item)) { | |
if (this.key) { | |
delete this.map[item[this.key]]; | |
} | |
this.list.splice(i, 1); | |
this.length = this.list.length; | |
return item; | |
} | |
} | |
} else { // item | |
if (this.key && this.map[fnOrKey] !== undefined) { | |
var item = this.map[fnOrKey]; | |
for(var i = 0, len = this.list.length; i < len; i++) { | |
if (this.list[i] === item) { | |
this.list.splice(i, 1); | |
this.length = this.list.length; | |
delete this.map[fnOrKey]; | |
return item; | |
} | |
} | |
} | |
} | |
return null; | |
}; | |
// remove by item or filter function | |
Collection.prototype.remove = function remove(fnOrItem) { | |
if (typeof fnOrItem === 'function') { // by function | |
for(var i = 0, len = this.list.length; i < len; i++) { | |
if(fnOrItem(this.list[i])) { | |
if (this.key) { | |
delete this.map[this.list[i][this.key]]; | |
} | |
this.list.splice(i, 1); | |
this.length = this.list.length; | |
return true; | |
} | |
} | |
} else { // by object | |
for(var i = 0, len = this.list.length; i < len; i++) { | |
if ((this.key && this.list[i][this.key] == fnOrItem[this.key]) || (this.list[i] === fnOrItem)) { | |
if (this.key) { | |
delete this.map[this.list[i][this.key]]; | |
} | |
this.list.splice(i, 1); | |
this.length = this.list.length; | |
return true; | |
} | |
} | |
} | |
return false; | |
}; | |
// get array (optionally filtered by function) | |
Collection.prototype.toArray = function toArray(fn) { | |
var res = [ ]; | |
if (fn) { | |
for(var i = 0, len = this.list.length; i < len; ++i) { | |
if (fn(this.list[i])) { | |
res.push(this.list[i]); | |
} | |
} | |
} else { | |
for(var i = 0, len = this.list.length; i < len; ++i) { | |
res.push(this.list[i]); | |
} | |
} | |
return res; | |
}; | |
// clear | |
Collection.prototype.clear = function clear() { | |
this.list = [ ]; | |
this.map = { }; | |
this.length = 0; | |
}; | |
// returns item by filter function or key | |
Collection.prototype.get = function get(fnOrKey) { | |
if (typeof(fnOrKey) === 'function') { // function | |
for(var i = 0, len = this.list.length; i < len; i++) { | |
if (fnOrKey(this.list[i])) { | |
return this.list[i]; | |
} | |
} | |
} else { // key | |
if (this.key && this.map[key] !== undefined) { | |
return this.map[key]; | |
} | |
} | |
return null; | |
}; | |
// return filtered list | |
Collection.prototype.filter = function filter(fn) { | |
return this.list.filter(fn); | |
}; | |
// for each call function | |
Collection.prototype.forEach = function forEach(fn) { | |
for(var i = 0, len = this.list.length; i < len; ++i) { | |
fn(this.list[i]); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment