var SearchContext, Search, Iterable; (function($) { "use strict"; try { Object.defineProperties($, { flatten: { value: function(linkedList) { var iterator, flattened = [], allowedPattern = /^(Array|Arguments)$/, className = Object.className(linkedList), callback = function(item) { if (!allowedPattern.test(Object.className(item))) { flattened.push(item); } }; if (className == "Arguments") { linkedList = $.from(linkedList); } else if (!allowedPattern.test(className)) { return linkedList; } // this way will treate all as String after run .join // linkedList = linkedList.join().split(","); iterator = SearchContext.Proxy .new(Search.Graphs.BFS.Object.new(linkedList)); iterator.research(callback); return flattened; } }, compact: { value: function(collection) { var callback = function(item) { if (typeof item == "string") { if (item !== "") { return true; } } else { if (item !== undefined && item !== null) { return true; } } }; return collection.filter(callback); } } }); Object.defineProperties($.prototype, { copy: { value: function(startingIndex, finalIndex) { return this.slice(startingIndex, finalIndex + 1); } }, clone: { value: function() { var clone = []; Object.assign(clone, this); return clone; } }, intersection: { value: function(set) { var smaller, larger, all = [this, set], classifier = function(first, second) { return first.length > second.length; }, callback = function(item) { return larger.includes(item); }; smaller = (all = all.sort(classifier)).first(); larger = all[1]; return smaller.filter(callback).uniq(); } }, intersections: { value: function(sets) { var smaller, self = this, all = Array.from(arguments), classifier = function(first, second) { return first.length > second.length; }, callback = function(intersections, set) { return intersections.intersection(set); }; all.push(self); all.sort(classifier); smaller = all.deleteAt(0); // reduce works with any value and it cans to reduce the list, filter works with true or false to filter values, and map replace the values. return all.reduce(callback, smaller.intersection(all.first())); } }, difference: { value: function(sets) { var self = this, differences = self.clone(), iteratorBlock = function(set) { var callback = function(item) { return !set.includes(item); }; differences = differences.filter(callback); }; sets = Array.from(arguments); if (sets.length < 1) { return this; } sets.uniq().forEach(iteratorBlock); return differences; } }, insertAt: { value: function(values, index) { var copy, self = this, argumentsAsArray = Array.from(arguments), callback = function(v) { self.push(v); }; index = argumentsAsArray.last(); copy = self.copy(index, self.lastIndex()); argumentsAsArray.deleteAt(argumentsAsArray.lastIndex()); self.deleteAt(index, self.lastIndex()); Array.prototype.push.apply(self, argumentsAsArray); copy.forEach(callback); return this; } }, indexOfEquivalence: { // value: function(comparator, startingIndex = 0) { value: function(comparator, startingIndex) { if(typeof startingIndex != "number") {startingIndex = 0;} var item, i = startingIndex; for (i = startingIndex; i < this.length; i++) { item = this[i]; if (typeof item == "function") { if (item == comparator) { return i; } } else { if (item === undefined) { console.warn("Item to compare is " + "undefined!"); } if (Object.areEquivalents(item, comparator)) { return i; } } } return -1; } }, uniq: { value: function() { var callback = function(reduced, value) { if (reduced.indexOfEquivalence(value) == -1) { reduced.push(value); } return reduced; }; return this.reduce(callback, []); } }, // already proposed in ES7 // includes: { // value: function(items) { // var // argumentsAsArray = Array.from(arguments).uniq(), // mainReference = this, // count = 0, // callback = function(arg) { // if (mainReference.indexOfEquivalence(arg) > -1) { // count += 1; // } // }; // argumentsAsArray.forEach(callback); // return count == argumentsAsArray.length; // } // }, deleteAt: { value: function(startingIndex, finalIndex) { var value, count = 1; if (typeof finalIndex == "number") { count = finalIndex + 1 - startingIndex; } value = this[startingIndex]; this.splice(startingIndex, count); return value; } }, delete: { value: function(collection) { var amount, index, deletedValue, self = this, deleted = [], partsToDelete = Array.from(arguments), callback = function(value) { amount = self.amount(value); while (amount-- > 0) { index = self.indexOfEquivalence(value); if (index > -1) { deletedValue = self[index]; self.splice(index, 1); } } if (index > -1) { deleted.push(deletedValue); } }; partsToDelete.forEach(callback); if (deleted.length > 1) { return deleted; } return deleted[0]; } }, without: { value: function(items) { var parts = Array.from(arguments), self = this, callback = function(item) { return !parts.includes(item); }; return self.filter(callback); } }, amount: { value: function(item) { var count = 0, i = 0; while (true) { i = this.indexOfEquivalence(item, i); if (i > -1) { count++; if (++i == this.length) { break; } } else { break; } } return count; } }, empty: { value: function() { return this.amount() === 0; } }, firstFromASlice: { value: function(slice, startingIndex, caseSensitive) { var regexp, iterator, clone = this.clone(), index = -1, iteratorBlock = function(v, i) { if (typeof v == "string" && i >= startingIndex) { if (v.search(regexp) != -1) { index = i; this.finalize(); } } }; if (typeof startingIndex != "number") { if (typeof startingIndex == "boolean") { caseSensitive = startingIndex; } startingIndex = 0; } if (typeof caseSensitive != "boolean") { caseSensitive = false; } if (startingIndex === 0) { clone = clone.asc(); } slice = slice.trim(); if (!caseSensitive) { regexp = new RegExp(slice, "i"); } else { regexp = new RegExp(slice); } iterator = Iterable.Proxy.new(this); iterator.each(iteratorBlock); return index; } }, countSlice: { value: function(slice, startingIndex, caseSensitive) { var i, regexp, clone = this.clone(), count = 0; if (typeof startingIndex != "number") { if (typeof startingIndex == "boolean") { caseSensitive = startingIndex; } startingIndex = 0; } if (typeof caseSensitive != "boolean") { caseSensitive = false; } if (startingIndex === 0) { clone = clone.asc(); } slice = slice.trim(); if (!caseSensitive) { regexp = new RegExp(slice, "i"); } else { regexp = new RegExp(slice); } i = parseInt(clone.firstFromASlice(slice, startingIndex, caseSensitive)); if (i > -1) { while (i < this.length) { if (clone[i].trim().search(regexp) > -1) { count += 1; i += 1; } else { break; } } } return count; } }, flatten: { value: function() { return $.flatten(this); } }, normalizeToLowerCase: { value: function() { var clone = [], callback = function(value) { if (typeof value == "string") { clone.push(value.toLowerCase()()); } }; this.forEach(callback); return clone; } }, capitalize: { value: function() { var clone = [], callback = function(value) { if (typeof value == "string") { clone.push(value.capitalize()); } }; this.forEach(callback); return clone; } }, spaceOut: { value: function() { var i = 0, clone = this.clone(); while (i < clone.lastIndex()) { clone[i++] += " "; } return clone; } }, compact: { value: function() { return $.compact(this); } }, asc: { value: function() { var clone = this.clone(), compareFunction = function(a, b) { return a > b; }; clone.sort(compareFunction); return clone; } }, desc: { value: function() { var clone = this.clone(), compareFunction = function(a, b) { return a < b; }; clone.sort(compareFunction); return clone; } }, lastIndex: { value: function() { return this.length - 1; } }, first: { value: function() { return this[0]; } }, last: { value: function() { return this[this.lastIndex()]; } } }); } catch(e) {} })(Array);